From 31d1caa526a7354ff608b6d44faeea2d04c68896 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 8 Jan 2015 17:51:52 +0100 Subject: [PATCH 01/18] Reverted some minor things, altered other things to get it to compile cleanly --- armsrc/appmain.c | 5 ++++- armsrc/apps.h | 2 +- armsrc/crapto1.c | 4 ++-- armsrc/mifarecmd.c | 24 ++++++++++++------------ client/cmdhflegic.c | 2 +- client/cmdhfmf.c | 3 +++ client/cmdlf.c | 1 + client/lualibs/html_dumplib.lua | 2 +- include/usb_cmd.h | 2 -- 9 files changed, 25 insertions(+), 20 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ca16ee60..530dc39c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -18,6 +18,7 @@ #include "util.h" #include "printf.h" #include "string.h" + #include #include "legicrf.h" @@ -667,7 +668,9 @@ 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(); SimulateTagLowFrequency(c->arg[0], c->arg[1], 1); + LED_A_OFF(); break; case CMD_LF_SIMULATE_BIDIR: SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); @@ -799,7 +802,7 @@ void UsbPacketReceived(uint8_t *packet, int len) MifareUReadBlock(c->arg[0],c->d.asBytes); break; case CMD_MIFAREU_READCARD: - MifareUReadCard(c->arg[0],c->d.asBytes); + MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); break; case CMD_MIFARE_READSC: MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); diff --git a/armsrc/apps.h b/armsrc/apps.h index eafee559..ce721525 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -177,7 +177,7 @@ void ReaderMifare(bool first_try); int32_t dist_nt(uint32_t nt1, uint32_t nt2); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareUReadBlock(uint8_t arg0,uint8_t *datain); -void MifareUReadCard(uint8_t arg0,uint8_t *datain); +void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0,uint8_t *datain); diff --git a/armsrc/crapto1.c b/armsrc/crapto1.c index df0834b8..9d491d12 100644 --- a/armsrc/crapto1.c +++ b/armsrc/crapto1.c @@ -44,12 +44,12 @@ static void quicksort(uint32_t* const start, uint32_t* const stop) else if(*rit > *start) --rit; else - *it ^= ( (*it ^= *rit ), *rit ^= *it); + *it ^= (*it ^= *rit, *rit ^= *it); if(*rit >= *start) --rit; if(rit != start) - *rit ^= ( (*rit ^= *start), *start ^= *rit); + *rit ^= (*rit ^= *start, *start ^= *rit); quicksort(start, rit - 1); quicksort(rit + 1, stop); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 2619a976..ecd8728d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -102,21 +102,21 @@ void MifareUReadBlock(uint8_t arg0,uint8_t *datain) int len = iso14443a_select_card(uid, NULL, &cuid); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(1); + //OnError(1); return; }; len = mifare_ultra_readblock(cuid, blockNo, dataout); if(len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); - OnError(2); + //OnError(2); return; }; len = mifare_ultra_halt(cuid); if(len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); + //OnError(3); return; }; @@ -201,11 +201,11 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) int count_Pages = 0; byte_t dataout[176] = {0x00};; uint8_t uid[10] = {0x00}; - uint32_t cuid; + uint32_t cuid; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Pages %d",Pages); @@ -218,7 +218,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) if (!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(1); + //OnError(1); return; } @@ -229,7 +229,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); - OnError(2); + //OnError(2); return; } else { count_Pages++; @@ -240,7 +240,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); + //OnError(3); return; } @@ -255,8 +255,8 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) len = 176; cmd_send(CMD_ACK, 1, 0, 0, dataout, len); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 35ba1f28..7ee601b2 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -16,7 +16,7 @@ #include "cmdparser.h" #include "cmdhflegic.h" #include "cmdmain.h" - +#include "util.h" static int CmdHelp(const char *Cmd); static command_t CommandTable[] = diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 66c0b25d..aae6290d 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -662,6 +662,8 @@ int CmdHF14AMfRestore(const char *Cmd) for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { if (fread(keyA[sectorNo], 1, 6, fkeys) == 0) { PrintAndLog("File reading error (dumpkeys.bin)."); + + fclose(fkeys); return 2; } } @@ -669,6 +671,7 @@ int CmdHF14AMfRestore(const char *Cmd) for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { if (fread(keyB[sectorNo], 1, 6, fkeys) == 0) { PrintAndLog("File reading error (dumpkeys.bin)."); + fclose(fkeys); return 2; } } diff --git a/client/cmdlf.c b/client/cmdlf.c index 572cda6c..65d6fdd5 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -19,6 +19,7 @@ #include "cmdparser.h" #include "cmdmain.h" #include "cmddata.h" +#include "util.h" #include "cmdlf.h" #include "cmdlfhid.h" #include "cmdlfti.h" diff --git a/client/lualibs/html_dumplib.lua b/client/lualibs/html_dumplib.lua index 44b6b352..3a28d5ae 100644 --- a/client/lualibs/html_dumplib.lua +++ b/client/lualibs/html_dumplib.lua @@ -49,7 +49,7 @@ end local function save_TEXT(data,filename) -- Open the output file - local outfile = io.open(filename, "wb") + local outfile = io.open(filename, "w") if outfile == nil then return oops(string.format("Could not write to file %s",tostring(filename))) end diff --git a/include/usb_cmd.h b/include/usb_cmd.h index c2e0b95b..69c3c1b6 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -150,10 +150,8 @@ typedef struct { #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 From 473124be92f5108df63146ef8b6be2a1db30b87a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 9 Jan 2015 21:51:34 +0100 Subject: [PATCH 02/18] removed double include --- client/cmdhw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 4f65fb8c..5ec0aa60 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -15,7 +15,6 @@ #include "ui.h" #include "proxmark3.h" #include "cmdparser.h" -#include "cmddata.h" #include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" From ac3ba7ee694dc67ee4c8bae293111b6c26f551a2 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 9 Jan 2015 16:46:17 -0500 Subject: [PATCH 03/18] lf search use new psk, small demod adjustments adjust thresholds for ask, fsk, io, psk based on more sample testing adjust indala decode to set clock to 32 if no input (autodetect not always correct) --- client/cmddata.c | 6 ++++- client/cmdlf.c | 58 ++++++++++++++++++++++++++++++------------------ common/lfdemod.c | 26 +++++++--------------- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 53a3ce5f..781ca50c 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -870,8 +870,12 @@ int PSKnrzDemod(const char *Cmd){ // optional arguments - same as CmdpskNRZrawDemod (clock & invert) int CmdIndalaDecode(const char *Cmd) { + int ans; + if (strlen(Cmd)>0) + ans=PSKnrzDemod(Cmd); + else + ans=PSKnrzDemod("32"); - int ans=PSKnrzDemod(Cmd); if (ans < 0){ PrintAndLog("Error1: %d",ans); return 0; diff --git a/client/cmdlf.c b/client/cmdlf.c index 18bcf747..d9fe5fa9 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -110,9 +110,9 @@ int CmdFlexdemod(const char *Cmd) i = 0; int phase = 0; for (bit = 0; bit < 64; bit++) { - + phase = (bits[bit] == 0) ? 0 : 1; - + int j; for (j = 0; j < 32; j++) { GraphBuffer[i++] = phase; @@ -123,7 +123,7 @@ int CmdFlexdemod(const char *Cmd) RepaintGraphWindow(); return 0; } - + int CmdIndalaDemod(const char *Cmd) { // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID @@ -167,7 +167,7 @@ int CmdIndalaDemod(const char *Cmd) count = 0; } } - + if (rawbit>0){ PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); @@ -198,7 +198,7 @@ int CmdIndalaDemod(const char *Cmd) break; } } - + if (start == rawbit - uidlen + 1) { PrintAndLog("nothing to wait for"); return 0; @@ -217,7 +217,7 @@ int CmdIndalaDemod(const char *Cmd) int bit; i = start; int times = 0; - + if (uidlen > rawbit) { PrintAndLog("Warning: not enough raw bits to get a full UID"); for (bit = 0; bit < rawbit; bit++) { @@ -235,12 +235,12 @@ int CmdIndalaDemod(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') { @@ -249,7 +249,7 @@ int CmdIndalaDemod(const char *Cmd) } else { uid1=(uid1<<1)|(uid2>>31); uid2=(uid2<<1)|1; - } + } } PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); } @@ -263,10 +263,10 @@ int CmdIndalaDemod(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; } PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); @@ -291,7 +291,7 @@ int CmdIndalaDemod(const char *Cmd) PrintAndLog("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; @@ -559,23 +559,37 @@ int CmdLFfind(const char *Cmd) ans=CmdSamples("20000"); } if (GraphTraceLen<1000) return 0; + PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag"); PrintAndLog("Checking for known tags:"); + ans=Cmdaskmandemod(""); - if (ans>0) return 1; + if (ans>0) { + PrintAndLog("Valid EM410x ID Found!"); + return 1; + } ans=CmdFSKdemodHID(""); - if (ans>0) return 1; + if (ans>0) { + PrintAndLog("Valid HID Prox ID Found!"); + return 1; + } ans=CmdFSKdemodIO(""); - if (ans>0) return 1; + if (ans>0) { + PrintAndLog("Valid IO Prox ID Found!"); + return 1; + } //add psk and indala - ans=CmdIndalaDemod(""); - if (ans>0) return 1; - ans=CmdIndalaDemod("224"); - if (ans>0) return 1; + ans=CmdIndalaDecode(""); + if (ans>0) { + PrintAndLog("Valid Indala ID Found!"); + return 1; + } + // ans=CmdIndalaDemod("224"); + // if (ans>0) return 1; PrintAndLog("No Known Tags Found!\n"); return 0; } -static command_t CommandTable[] = +static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, @@ -602,7 +616,7 @@ static command_t CommandTable[] = int CmdLF(const char *Cmd) { CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) diff --git a/common/lfdemod.c b/common/lfdemod.c index 25e52552..11ad1403 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -300,7 +300,7 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert) else if (BinStream[i] < low) low = BinStream[i]; } - if ((high < 158)){ //throw away static + if ((high < 134)){ //throw away static high has to be more than 6 on graph. noise <= -10 here // PrintAndLog("no data found"); return -2; } @@ -407,21 +407,11 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow { uint32_t last_transition = 0; uint32_t idx = 1; - uint32_t maxVal=0; + //uint32_t maxVal=0; if (fchigh==0) fchigh=10; if (fclow==0) fclow=8; - // we do care about the actual theshold value as sometimes near the center of the - // wave we may get static that changes direction of wave for one value - // if our value is too low it might affect the read. and if our tag or - // antenna is weak a setting too high might not see anything. [marshmellow] - if (size<100) return 0; - for(idx=1; idx<100; idx++){ - if(maxVal Date: Sun, 11 Jan 2015 21:49:13 +0100 Subject: [PATCH 04/18] Fixed error when no match is found for uidmapping --- client/cmdhf14a.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 53ab240c..01602d76 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -112,20 +112,15 @@ const manufactureName manufactureMapping[] = { // returns description of the best match char* getTagInfo(uint8_t uid) { - int i, best = -1; + int i; int len = sizeof(manufactureMapping) / sizeof(manufactureName); - for ( i = 0; i < len; ++i ) { - if ( uid == manufactureMapping[i].uid) { - if (best == -1) { - best = i; - } - } - } + for ( i = 0; i < len; ++i ) + if ( uid == manufactureMapping[i].uid) + return manufactureMapping[i].desc; - if (best>=0) return manufactureMapping[best].desc; - - return manufactureMapping[i].desc; + //No match, return default + return manufactureMapping[len-1].desc; } int CmdHF14AList(const char *Cmd) From 1f6417a9b25f05a29e8de171fb26022c996453b3 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 12 Jan 2015 21:47:36 +0100 Subject: [PATCH 05/18] Removed dependency on openssl, added AES implementation from polarssl instead --- client/Makefile | 5 +++-- client/scripting.c | 20 ++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/client/Makefile b/client/Makefile index 37616e48..523a1ad1 100644 --- a/client/Makefile +++ b/client/Makefile @@ -13,9 +13,9 @@ CXX=g++ VPATH = ../common OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm -lcrypto +LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm LDFLAGS = $(COMMON_FLAGS) -CFLAGS = -std=c99 -lcrypto -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 +CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) @@ -94,6 +94,7 @@ CMDSRCS = nonce2key/crapto1.c\ scripting.c\ cmdscript.c\ pm3_bitlib.c\ + aes.c\ COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) diff --git a/client/scripting.c b/client/scripting.c index eed5544b..0ccdeeec 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -18,8 +18,8 @@ #include "util.h" #include "nonce2key/nonce2key.h" #include "../common/iso15693tools.h" -#include #include "../common/crc16.h" +#include "aes.h" /** * The following params expected: * UsbCommand c @@ -240,10 +240,10 @@ static int l_aes(lua_State *L) const char *p_encTxt = luaL_checklstring(L, 2, &size); - unsigned char indata[AES_BLOCK_SIZE] = {0x00}; - unsigned char outdata[AES_BLOCK_SIZE] = {0x00}; - unsigned char aes_key[AES_BLOCK_SIZE] = {0x00}; - unsigned char iv[AES_BLOCK_SIZE] = {0x00}; + unsigned char indata[16] = {0x00}; + unsigned char outdata[16] = {0x00}; + unsigned char aes_key[16] = {0x00}; + unsigned char iv[16] = {0x00}; // convert key to bytearray for (i = 0; i < 32; i += 2) { @@ -255,10 +255,14 @@ static int l_aes(lua_State *L) sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); } - AES_KEY key; - AES_set_decrypt_key(aes_key, 128, &key); - AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT); + //AES_KEY key; + //AES_set_decrypt_key(aes_key, 128, &key); + //AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT); + aes_context ctx; + aes_init(&ctx); + aes_setkey_enc(&ctx,(const unsigned char *)p_key,128); + aes_crypt_cbc(&ctx,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 From 55eaed8f2ad26b9db249e2259c13444c38906795 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 12 Jan 2015 22:08:57 +0100 Subject: [PATCH 06/18] Documentation to apps.h, documentation/renaming to iclass --- armsrc/apps.h | 19 ++++++++++ armsrc/iclass.c | 96 +++++++++++++++++++++++++++---------------------- 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index eafee559..ea70144e 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -37,6 +37,25 @@ uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)]; #define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE) #define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1) +/* +The statements above translates into this : +BIGBUF_SIZE = 40000 +TRACE_OFFSET = 0 +TRACE_SIZE = 3000 +RECV_CMD_OFFSET = 3000 +MAX_FRAME_SIZE = 256 +MAX_PARITY_SIZE = 32 +RECV_CMD_PAR_OFFSET = 3256 +RECV_RESP_OFFSET = 3288 +RECV_RESP_PAR_OFFSET= 3544 +CARD_MEMORY_OFFSET = 3576 +CARD_MEMORY_SIZE = 4096 +DMA_BUFFER_OFFSET = 3576 +DMA_BUFFER_SIZE = 4096 +FREE_BUFFER_OFFSET = 7672 +FREE_BUFFER_SIZE = 32327 + */ + extern const uint8_t OddByteParity[256]; extern uint8_t *trace; // = (uint8_t *) BigBuf; extern int traceLen; // = 0; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index ea9af7d4..64abc84a 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -687,7 +687,8 @@ void RAMFUNC SnoopIClass(void) SetAdcMuxFor(GPIO_MUXSEL_HIPKD); uint32_t time_0 = GetCountSspClk(); - + uint32_t time_start = 0; + uint32_t time_stop = 0; int div = 0; //int div2 = 0; @@ -738,6 +739,7 @@ void RAMFUNC SnoopIClass(void) smpl = decbyter; if(OutOfNDecoding((smpl & 0xF0) >> 4)) { rsamples = samples - Uart.samples; + time_stop = (GetCountSspClk()-time_0) << 4; LED_C_ON(); //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break; @@ -745,7 +747,7 @@ void RAMFUNC SnoopIClass(void) if(tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE); + LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, TRUE); } @@ -756,6 +758,8 @@ void RAMFUNC SnoopIClass(void) Demod.state = DEMOD_UNSYNCD; LED_B_OFF(); Uart.byteCnt = 0; + }else{ + time_start = (GetCountSspClk()-time_0) << 4; } decbyter = 0; } @@ -763,21 +767,24 @@ void RAMFUNC SnoopIClass(void) if(div > 3) { smpl = decbyte; if(ManchesterDecoding(smpl & 0x0F)) { - rsamples = samples - Demod.samples; + time_stop = (GetCountSspClk()-time_0) << 4; + + rsamples = samples - Demod.samples; LED_B_ON(); if(tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(Demod.output, Demod.len, parity); - LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE); + LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, FALSE); } - // And ready to receive another response. memset(&Demod, 0, sizeof(Demod)); Demod.output = tagToReaderResponse; Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); + }else{ + time_start = (GetCountSspClk()-time_0) << 4; } div = 0; @@ -928,6 +935,7 @@ static void CodeIClassTagSOF() // Convert from last byte pos to length ToSendMax++; } + int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf); /** * @brief SimulateIClass simulates an iClass card. @@ -997,7 +1005,9 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain */ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf) { + // CSN followed by two CRC bytes + uint8_t response1[] = { 0x0F} ; uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t response3[] = { 0,0,0,0,0,0,0,0,0,0}; memcpy(response3,csn,sizeof(response3)); @@ -1020,11 +1030,11 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader // Reader 81 anticoll. CSN // Tag CSN - uint8_t *resp; - int respLen; - uint8_t* respdata = NULL; - int respsize = 0; - uint8_t sof = 0x0f; + uint8_t *modulated_response; + int modulated_response_size; + uint8_t* trace_data = NULL; + int trace_data_size = 0; + //uint8_t sof = 0x0f; // Respond SOF -- takes 8 bytes uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); @@ -1089,11 +1099,6 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader LED_A_ON(); bool buttonPressed = false; - /** Hack for testing - memcpy(reader_mac_buf,csn,8); - exitLoop = true; - end hack **/ - while(!exitLoop) { LED_B_OFF(); @@ -1112,35 +1117,35 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader // Okay, look at the command now. if(receivedCmd[0] == 0x0a ) { // Reader in anticollission phase - resp = resp1; respLen = resp1Len; //order = 1; - respdata = &sof; - respsize = sizeof(sof); + modulated_response = resp1; modulated_response_size = resp1Len; //order = 1; + trace_data = response1; + trace_data_size = sizeof(response1); } else if(receivedCmd[0] == 0x0c) { // Reader asks for anticollission CSN - resp = resp2; respLen = resp2Len; //order = 2; - respdata = response2; - respsize = sizeof(response2); + modulated_response = resp2; modulated_response_size = resp2Len; //order = 2; + trace_data = response2; + trace_data_size = sizeof(response2); //DbpString("Reader requests anticollission CSN:"); } else if(receivedCmd[0] == 0x81) { // Reader selects anticollission CSN. // Tag sends the corresponding real CSN - resp = resp3; respLen = resp3Len; //order = 3; - respdata = response3; - respsize = sizeof(response3); + modulated_response = resp3; modulated_response_size = resp3Len; //order = 3; + trace_data = response3; + trace_data_size = sizeof(response3); //DbpString("Reader selects anticollission CSN:"); } else if(receivedCmd[0] == 0x88) { // Read e-purse (88 02) - resp = resp4; respLen = resp4Len; //order = 4; - respdata = response4; - respsize = sizeof(response4); + modulated_response = resp4; modulated_response_size = resp4Len; //order = 4; + trace_data = response4; + trace_data_size = sizeof(response4); LED_B_ON(); } else if(receivedCmd[0] == 0x05) { // Reader random and reader MAC!!! // Do not respond // We do not know what to answer, so lets keep quiet - resp = resp1; respLen = 0; //order = 5; - respdata = NULL; - respsize = 0; + modulated_response = resp1; modulated_response_size = 0; //order = 5; + trace_data = NULL; + trace_data_size = 0; if (breakAfterMacReceived){ // dbprintf:ing ... Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x" @@ -1157,9 +1162,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader } } else if(receivedCmd[0] == 0x00 && len == 1) { // Reader ends the session - resp = resp1; respLen = 0; //order = 0; - respdata = NULL; - respsize = 0; + modulated_response = resp1; modulated_response_size = 0; //order = 0; + trace_data = NULL; + trace_data_size = 0; } else { //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 // Never seen this command before @@ -1169,9 +1174,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader receivedCmd[3], receivedCmd[4], receivedCmd[5], receivedCmd[6], receivedCmd[7], receivedCmd[8]); // Do not respond - resp = resp1; respLen = 0; //order = 0; - respdata = NULL; - respsize = 0; + modulated_response = resp1; modulated_response_size = 0; //order = 0; + trace_data = NULL; + trace_data_size = 0; } if(cmdsRecvd > 100) { @@ -1181,9 +1186,16 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader else { cmdsRecvd++; } - - if(respLen > 0) { - SendIClassAnswer(resp, respLen, 21); + /** + After changes to parity calculation + Time between reader EOT and pm3 SOF + delay 21 -> 480uS + delay 10 -> 220us + delay 16 -> 388us + A legit tag has about 380us. + **/ + if(modulated_response_size > 0) { + SendIClassAnswer(modulated_response, modulated_response_size, timeout); t2r_time = GetCountSspClk(); } @@ -1192,9 +1204,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader GetParity(receivedCmd, len, parity); LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE); - if (respdata != NULL) { - GetParity(respdata, respsize, parity); - LogTrace(respdata, respsize, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE); + if (trace_data != NULL) { + GetParity(trace_data, trace_data_size, parity); + LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE); } if(!tracing) { DbpString("Trace full"); From 896473399bbe08d9a2d0a65763d49fd95613d8a6 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 12 Jan 2015 22:16:46 +0100 Subject: [PATCH 07/18] Actually add the FILES also, doh --- client/aes.c | 1454 +++++++++++++++++++++++++ client/aes.h | 257 +++++ client/polarssl_config.h | 2179 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 3890 insertions(+) create mode 100644 client/aes.c create mode 100644 client/aes.h create mode 100644 client/polarssl_config.h diff --git a/client/aes.c b/client/aes.c new file mode 100644 index 00000000..36f735d4 --- /dev/null +++ b/client/aes.c @@ -0,0 +1,1454 @@ +/* + * 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/client/aes.h b/client/aes.h new file mode 100644 index 00000000..946bd87d --- /dev/null +++ b/client/aes.h @@ -0,0 +1,257 @@ +/** + * \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/client/polarssl_config.h b/client/polarssl_config.h new file mode 100644 index 00000000..5bd88fc0 --- /dev/null +++ b/client/polarssl_config.h @@ -0,0 +1,2179 @@ +/** + * \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 84871873a41a6eb80dd836efdbf4722ffcea089a Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 13 Jan 2015 17:21:36 -0500 Subject: [PATCH 08/18] Small lf bug fixes and threshold adjustments adjusted lf demod thresholds based on additional testing fixed bug in hid bit length calc in cmddata.c fixed bugs in lf search --- client/cmddata.c | 53 +++++++++++++++++++++++++++++++----------------- client/cmdlf.c | 33 ++++++++++++++++++++---------- common/lfdemod.c | 34 +++++++++++++++---------------- 3 files changed, 73 insertions(+), 47 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index ed0a0758..a88fa4e1 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -618,7 +618,7 @@ int CmdFSKdemodHID(const char *Cmd) 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 & 15) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit + 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=lo2>>1; @@ -631,10 +631,6 @@ int CmdFSKdemodHID(const char *Cmd) cardnum = (lo>>1)&0xFFFF; fc = (lo>>17)&0xFF; } - if(fmtLen==37){ - cardnum = (lo>>1)&0x7FFFF; - fc = ((hi&0xF)<<12)|(lo>>20); - } if(fmtLen==34){ cardnum = (lo>>1)&0xFFFF; fc= ((hi&1)<<15)|(lo>>17); @@ -645,10 +641,10 @@ int CmdFSKdemodHID(const char *Cmd) } } else { //if bit 38 is not set then 37 bit format is used - fmtLen= 37; - fc =0; - cardnum=0; - if(fmtLen==37){ + fmtLen = 37; + fc = 0; + cardnum = 0; + if(fmtLen == 37){ cardnum = (lo>>1)&0x7FFFF; fc = ((hi&0xF)<<12)|(lo>>20); } @@ -870,24 +866,35 @@ int PSKnrzDemod(const char *Cmd){ // optional arguments - same as CmdpskNRZrawDemod (clock & invert) int CmdIndalaDecode(const char *Cmd) { - int ans; - if (strlen(Cmd)>0) - ans=PSKnrzDemod(Cmd); - else - ans=PSKnrzDemod("32"); + uint8_t verbose = 1; + int ans; + if (strlen(Cmd)>0){ + if (Cmd[0]=='0'){ + verbose=0; + ans = PSKnrzDemod("32"); + }else{ + ans = PSKnrzDemod(Cmd); + } + } else{ //default to RF/32 + ans = PSKnrzDemod("32"); + } if (ans < 0){ - PrintAndLog("Error1: %d",ans); + if (verbose) + PrintAndLog("Error1: %d",ans); return 0; } uint8_t invert=0; ans = indala26decode(DemodBuffer,(size_t *) &DemodBufferLen, &invert); if (ans < 1) { - PrintAndLog("Error2: %d",ans); + if (verbose) + PrintAndLog("Error2: %d",ans); return -1; } char showbits[251]; - if(invert==1) PrintAndLog("Had to invert bits"); + if (invert) + if (verbose) + PrintAndLog("Had to invert bits"); //convert UID to HEX uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; int idx; @@ -951,11 +958,19 @@ int CmdPskClean(const char *Cmd) //prints binary found and saves in graphbuffer for further commands int CmdpskNRZrawDemod(const char *Cmd) { - int errCnt= PSKnrzDemod(Cmd); + uint8_t verbose = 1; + int errCnt; + if (strlen(Cmd)>0){ + if (Cmd[0]=='0') + verbose=0; + } + + errCnt = PSKnrzDemod(Cmd); //output if (errCnt<0) return 0; if (errCnt>0){ - PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt); + if (verbose) + PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt); } PrintAndLog("PSK or NRZ demoded bitstream:"); // Now output the bitstream to the scrollback by line of 16 bits diff --git a/client/cmdlf.c b/client/cmdlf.c index 65d6fdd5..e3361cb5 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -566,26 +566,37 @@ int CmdLFfind(const char *Cmd) return 0; } - if (!offline || (cmdp != '1') ){ + if (!offline && (cmdp != '1')){ ans=CmdLFRead(""); - ans=CmdSamples("20000"); + ans=CmdSamples("20000"); } else if (GraphTraceLen < 1000) { PrintAndLog("Data in Graphbuffer was too small."); return 0; } + PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag"); PrintAndLog("Checking for known tags:"); - ans=Cmdaskmandemod(""); - if (ans>0) return 1; - ans=CmdFSKdemodHID(""); - if (ans>0) return 1; ans=CmdFSKdemodIO(""); - if (ans>0) return 1; + if (ans>0) { + PrintAndLog("Valid IO Prox ID Found!"); + return 1; + } + ans=CmdFSKdemodHID(""); + if (ans>0) { + PrintAndLog("Valid HID Prox ID Found!"); + return 1; + } //add psk and indala - ans=CmdIndalaDemod(""); - if (ans>0) return 1; - ans=CmdIndalaDemod("224"); - if (ans>0) return 1; + ans=CmdIndalaDecode("0"); + if (ans>0) { + PrintAndLog("Valid Indala ID Found!"); + return 1; + } + ans=Cmdaskmandemod(""); + if (ans>0) { + PrintAndLog("Valid EM410x ID Found!"); + return 1; + } PrintAndLog("No Known Tags Found!\n"); return 0; } diff --git a/common/lfdemod.c b/common/lfdemod.c index 11ad1403..2352caad 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -19,7 +19,7 @@ uint64_t Em410xDecode(uint8_t *BitStream, size_t size) //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future // otherwise could be a void with no arguments //set defaults - int high=0, low=128; + int high=0, low=255; uint64_t lo=0; uint32_t i = 0; @@ -84,7 +84,7 @@ uint64_t Em410xDecode(uint8_t *BitStream, size_t size) int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert) { int i; - int high = 0, low = 128; + int high = 0, low = 255; *clk=DetectASKClock(BinStream, *size, *clk); //clock default if (*clk<8) *clk =64; @@ -100,7 +100,7 @@ int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert) else if (BinStream[i] < low) low = BinStream[i]; } - if ((high < 158) ){ //throw away static + if ((high < 129) ){ //throw away static (anything < 1 graph) //PrintAndLog("no data found"); return -2; } @@ -283,7 +283,7 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert) { uint32_t i; // int invert=0; //invert default - int high = 0, low = 128; + int high = 0, low = 255; *clk=DetectASKClock(BinStream, *size, *clk); //clock default uint8_t BitStream[502] = {0}; @@ -300,7 +300,8 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert) else if (BinStream[i] < low) low = BinStream[i]; } - if ((high < 134)){ //throw away static high has to be more than 6 on graph. noise <= -10 here + if ((high < 129)){ //throw away static high has to be more than 0 on graph. + //noise <= -10 here // PrintAndLog("no data found"); return -2; } @@ -410,8 +411,8 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow //uint32_t maxVal=0; if (fchigh==0) fchigh=10; if (fclow==0) fclow=8; - //set the threshold close to 0 (graph) to avoid static - uint8_t threshold_value = 134; //(uint8_t)(((maxVal-128)*.75)+128); + //set the threshold close to 0 (graph) or 128 std to avoid static + uint8_t threshold_value = 123; // sync to first lo-hi transition, and threshold @@ -471,7 +472,7 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t maxCons if ( dest[idx-1]==1 ) { n=myround2((float)(n+1)/((float)(rfLen)/(float)fclow)); } else {// 0->1 crossing - n=myround2((float)(n+1)/((float)(rfLen-2)/(float)fchigh)); //-2 for fudge factor + n=myround2((float)(n+1)/((float)(rfLen-1)/(float)fchigh)); //-1 for fudge factor } if (n == 0) n = 1; @@ -563,7 +564,7 @@ uint32_t bytebits_to_byte(uint8_t* src, size_t numbits) int IOdemodFSK(uint8_t *dest, size_t size) { - static const uint8_t THRESHOLD = 134; + static const uint8_t THRESHOLD = 129; uint32_t idx=0; //make sure buffer has data if (size < 66) return -1; @@ -607,7 +608,7 @@ int DetectASKClock(uint8_t dest[], size_t size, int clock) { int i=0; int peak=0; - int low=128; + int low=255; int clk[]={16,32,40,50,64,100,128,256}; int loopCnt = 256; //don't need to loop through entire array... if (size 1280) gLen=1280; // get high @@ -889,7 +889,7 @@ int pskNRZrawDemod(uint8_t *dest, size_t *size, int *clk, int *invert) int lastBit = 0; //set first clock check uint32_t bitnum = 0; //output counter 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=2; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely + if (*clk==32) tol = 2; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely uint32_t iii = 0; uint8_t errCnt =0; uint32_t bestStart = *size; From dc065b4e3467effd6b4f695dd3bc781da872d394 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 13 Jan 2015 17:52:48 -0500 Subject: [PATCH 09/18] slight em410xdecode adjustments a little faster --- common/lfdemod.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 2352caad..062818ef 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -19,21 +19,9 @@ uint64_t Em410xDecode(uint8_t *BitStream, size_t size) //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future // otherwise could be a void with no arguments //set defaults - int high=0, low=255; uint64_t lo=0; - uint32_t i = 0; - uint32_t initLoopMax = 65; - if (initLoopMax>size) initLoopMax=size; - - for (;i < initLoopMax; ++i) //65 samples should be plenty to find high and low values - { - if (BitStream[i] > high) - high = BitStream[i]; - else if (BitStream[i] < low) - low = BitStream[i]; - } - if (((high !=1)||(low !=0))){ //allow only 1s and 0s + if (BitStream[10]>1){ //allow only 1s and 0s // PrintAndLog("no data found"); return 0; } @@ -51,9 +39,9 @@ uint64_t Em410xDecode(uint8_t *BitStream, size_t size) idx+=9; for (i=0; i<10;i++){ for(ii=0; ii<5; ++ii){ - parityTest += BitStream[(i*5)+ii+idx]; + parityTest ^= BitStream[(i*5)+ii+idx]; } - if (parityTest== ((parityTest>>1)<<1)){ + if (!parityTest){ parityTest=0; for (ii=0; ii<4;++ii){ lo=(lo<<1LL)|(BitStream[(i*5)+ii+idx]); @@ -63,7 +51,7 @@ uint64_t Em410xDecode(uint8_t *BitStream, size_t size) //PrintAndLog("DEBUG: EM parity failed parity val: %d, i:%d, ii:%d,idx:%d, Buffer: %d%d%d%d%d",parityTest,i,ii,idx,BitStream[idx+ii+(i*5)-5],BitStream[idx+ii+(i*5)-4],BitStream[idx+ii+(i*5)-3],BitStream[idx+ii+(i*5)-2],BitStream[idx+ii+(i*5)-1]); parityTest=0; idx-=8; - if (resetCnt>5)return 0; + if (resetCnt>5)return 0; //try 5 times resetCnt++; goto restart;//continue; } From 645c960f6111f4820c78c76f209479c3f369a8ac Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 15:16:34 +0100 Subject: [PATCH 10/18] Implemented new FPGA mode for iclass tag simulation. Reduces arm-side size of transfer/memory by a factor of 8. Makes for easier arm-side encoding of messages, for when we start needing to do that on the fly instead of using precalculated messages --- armsrc/apps.h | 2 + armsrc/iclass.c | 136 +++++++++++++++++++++++++++------------------ fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/hi_simulate.v | 39 +++++++++++-- 4 files changed, 118 insertions(+), 59 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index ea70144e..6a3fa186 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -134,6 +134,8 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) #define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) #define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) +#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101 + // Options for ISO14443A #define FPGA_HF_ISO14443A_SNIFFER (0<<0) #define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 64abc84a..329e1765 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -857,57 +857,93 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) } } +static uint8_t encode4Bits(const uint8_t b) +{ + uint8_t c = b & 0xF; + // OTA, the least significant bits first + // The columns are + // 1 - Bit value to send + // 2 - Reversed (big-endian) + // 3 - Encoded + // 4 - Hex values + + 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) { - //So far a dummy implementation, not used - //int lastProxToAirDuration =0; + + /* + * 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 inptu to the FPGA becomes an unmodulated time of 18.88us + * + * In thist mode the SOF can be written as 00011101 = 0x1D + * The EOF can be written as 10111000 = 0xb8 + * A logic 1 is 01 + * A logic 0 is 10 + * + * */ + int i; ToSendReset(); // Send SOF - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff;//Proxtoair duration starts here - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; + ToSend[++ToSendMax] = 0x1D; for(i = 0; i < len; i++) { - int j; uint8_t b = cmd[i]; - - // Data bits - for(j = 0; j < 8; j++) { - if(b & 1) { - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; - } else { - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0x00; - } - b >>= 1; - } + ToSend[++ToSendMax] = encode4Bits(b & 0xF); //Least significant half + ToSend[++ToSendMax] = encode4Bits((b >>4) & 0xF);//Most significant half } // Send EOF - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - + 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++; } @@ -920,18 +956,9 @@ static void CodeIClassTagSOF() ToSendReset(); // Send SOF - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; - + ToSend[++ToSendMax] = 0x1D; // lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning - // Convert from last byte pos to length ToSendMax++; } @@ -984,6 +1011,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain memcpy(csn_crc, datain+(i*8), 8); if(doIClassSimulation(csn_crc,1,mac_responses+i*8)) { + cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8); return; // Button pressed } } @@ -1036,23 +1064,23 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader int trace_data_size = 0; //uint8_t sof = 0x0f; - // Respond SOF -- takes 8 bytes + // Respond SOF -- takes 1 bytes uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); int resp1Len; // Anticollision CSN (rotated CSN) - // 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit) - uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 10); + // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) + uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 2); int resp2Len; // CSN - // 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit) - uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 190); + // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) + uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 30); int resp3Len; // e-Purse - // 144: Takes 16 bytes for SOF/EOF and 8 * 16 = 128 bytes (2 bytes/bit) - uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 370); + // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/byte) + uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 60); int resp4Len; // + 1720.. @@ -1195,7 +1223,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader A legit tag has about 380us. **/ if(modulated_response_size > 0) { - SendIClassAnswer(modulated_response, modulated_response_size, timeout); + SendIClassAnswer(modulated_response, modulated_response_size, 1); t2r_time = GetCountSspClk(); } @@ -1232,7 +1260,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay) int i = 0, d=0;//, u = 0, d = 0; uint8_t b = 0; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K); + //FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); AT91C_BASE_SSC->SSC_THR = 0x00; FpgaSetupSsc(); @@ -1256,7 +1285,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay) AT91C_BASE_SSC->SSC_THR = b; } - if (i > respLen +4) break; +// if (i > respLen +4) break; + if (i > respLen +1) break; } return 0; diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 5389428c5539eb60eee9f27b6956ca950aa79b15..8b0c7a3788ef438c94eaed81346a08f24927f954 100644 GIT binary patch literal 42175 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 literal 42175 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

eu*}zWMx6WDri0MtNP{{*8u|VkeY~bQJ-m} z7M)*%{Fekx&IC-iaV?u=LLrBPKDS_pSS>~mx7mKh34t=T#Fp*W-`gBs+w!t8Zoa__ zx4qxTuiw&P*>)3H|JCex$V+~TaiNw^hK}`Ddh4~+9x>tkMWbUF#US?KW)lK?R?z`b zte;P=cTg?gBLG_gr0On(up6C+eu;p_o%-4Lgirz^(WXi8{QT`U9yAl& zsE%-}Wpa+=rE!yU=zyA+LYt_!rd)q`sBcj^Hf1amUj3mpH}G3^bt2YnEEK$4x_+L^ zUt3fCJRHE*!~HlQU@psIANu&k+5g3f*wl(;5U$Mu5Ig9c(>V#2P2PG9&D;*RuyL^Y z)&5&qzucN1i#Zbdl|^E1p*PP&9Aj*dLp{LUN5J*qR6rTyUmit{j9>)uIc8P0 zU94pN%2v&ReqkTF;3=l3Uqh(xgf6;!Dy$ms`E&QeEvm$4%liW(>1;b(+xhD#cqGM zJ2r`cwqHLVTE3C3`d+b6w}C4gqeq<<7e12Xt%Vsh14&A&s3UIhY-XVlF-m^@Jn9b* zVjp&^#(e$Zq^0ec8%kT`=~w!SDY%ZEw8aI~`at$;;l&Rt^`7Va7d-qN+>E!eUJwqh zh)V#p#7^+}7pgVfmIsjSIsw>f$!-1zz}8?N{M8cvg~*bPnO}-f4A#Q6?8_(xv^t1A z=JT(Ic*qJ!eZtZ6vsZw!nL7^x3w-{imw-8bevb{VSR@glBJhh6{)L)kg+8C6zXCvS zdEGe9M2ukPeg5?jmJ%#GQ+Q9x3J?n9()vAm|1keTzFXnzvfN4R4?L5O)3Av zaH1|oG3JdcDZ*R(1jb&%zvc!XVKiSSUbJ=n{2$&uSA0F?{7F?A|3cc!jmE*h_JDT5 z6ok}48|T_e_}2kmCZ$K=uh$!OfAwlPereUq7!zJu%YYFJz;B^g3IEy=gzu-UUU5w8 zm$e8sp`RKkT*klh6(%oIUcia4K8Hu)^DmBX#FP~%jJ;iif(QttpkIFeYlz-Vcc}0X z`UCt@;RjIXIg;K}#=jV?usVa-Q5wGjhJI4Jx&*)2RO)D0x~t3h7uHll^-gKi4g9K5_XZjz+W7p7Eq{Zwxc-n~>+;%U-OlyV zc{eO9;a>@w8sKOcW&?c=gf|(HloSuR*x?gJ{K{8ryn_9FEgQ7^RvuEB+(qgSIhDXl zWM$|MY}&sB7L?-`%%ESkF@-{oXVv0{QvS6=GHjtg`HtO*jdV9P1WWnX4%ASUw&Bf& zHdM~P7`Cif625T|Hgns~QI2oK+1do-jB#8)ul4<*{#Hi|DddHZ1loQQg1#5{mmbbo zI1PTG+Z-?^YR}Mt>HLei419h^+m@_h%0sj`7n>~PzjXb40A?`V#ry)oflUj=gX&>3 z3~nWD?vH}a)TY}n+t?m-#NbR6rK3#&zu@8XaPn(<@N!28N>h`2RlE@2;QD#)>T2&j z9qyKt;m{adXN+q)|4MKgg*(qch71eA9{T+2C&0MHCRXQdl+AZK5IT?m)reMtU&w!5 z3bZ;wFR7OFV1_YQV1Q-#m7yqM=EqUU(V`Y|%yZcDB?|a86ZmC*$;L=e@R5N`wZ?7+ z`V#yam*?C^B}Q>Vy@Z2%_hs_9ygIX@h+n~T?lt2Wg&vox@{*F*xOn2@*FVuA3Gbcj z91u3l6cUAH=f7Iv7S3?dpQ9)mY1xHtoMiuS5<)S4$WaTF7meghH6fuY~vMrTs@%Af7z1Po#TfGopu$9&l(j78>%bgD~^8h&DvfU z^&8I%Zi4!aeYIGo9*p7z4P+?WI6L!P@UM7W*~$dB;rQXxiMGLT<`O+Fr3VP$U>)@1 zhdZd>)Y)xacBrDgQ2d9f`5+F0`StUU(}pBcb?Yk6n<(UXwO$vWsOB6x@8j2)=*Q}z0E*Y5KPmVku)6@S+V*R`~J59CjVzv??+|$EXEDHEaTBLdx+= zGDEEON+r?xZ5&L)lOle7SM7JuCKVayLXMR#~YL#i?Y_15x2XOU;2Xigf&!N;#U0=sd|UU3#gtkqr6EB+1f zx;3flGW8y4;#F{5sp$IeE|2 zidSF{@t!FJBoXa#0EmA4@bA!{)=~85W%Q?c6y2!fLPWC4>gV@Lug~He)I4G)s%;)c z!t(Q9PTg|~xe1KD_Bq(h*fFd+5uQlsmycgRP*bw=WGrJmzfq3rsLJ zpw9>!Lcbi(CZO|0{L=gjJq&Q!{FQP>4)_H|Ceddfzh2>JAy=6q1gEay_39-Qau9^L z^f(&o4>xkP;Sl!EenLPg-h}{;YH@&Q`S>B%AL)7xwINn`O1V+!k z#Ctd%)r#TJIfV@7WWSGJ56RcDSHnB8+(>RdiT6~WS)a zJ3oX#IRCZsZU|B4U)pbB{Q7rlcf*bWSJr7CL)t3{2Hk#hD4z833+I*t?NB1)V#-iW~L@cgjdxQo|4pIb-$p@3y`wZF;&6m1NF=m*>z znSbfAEBba|lWNG}wvAU@Bu#RlT|Wt~S8Ec$FPC&1KEJHGol5OTZC3i=!_lh#zQps` zhxzyD`#0opDx5&}nU(>PlmP@`PWK@Eg(^KQ|(6DDWj=sKE$+BntvmF{A!|msWr=CL#dOk+eA!a z_o8tTzk;ypC<6dB1AZYG0#cLi8**-7EU4gV*7fsa?CB|^np}#rS&pc&oo!JF{`s#_ zjRoN>?EHH}od0?f`7hS5lyThK&)X|bVO-#qHdK!T+A)szGJ-%T;1}g+kWjzjisLk> zI1v_sYQZL$ZlQjoyJEEJUZpvsE7qG0U1m@6QWKj^cK3+q3;c`qtFhP0GA=uf5(PZ% z^dr%FgP9d4JX@EZJ<8MDqag{2FgYh>ebhcZ+TMc+&)09P4S;`%$9WX4H$dRm!086P zIxl*AgYVyXflF~l497vZCJ=HBJ~7kz5je?y{!51qx8s1>V%k(60c<6&ayA88(y#zW z^faS><2tn!-mv9VhGakObcdE!him{@7JKZ7r#tDHa~J|#+-4I}159D$r)y~-*enpQ z8?&{34bi3a6LoC@c5Lp*b1-P33GAOy01z$|I)WG;e$3hTuz82>SSO|4hp80^VgQB1 z4;T0s*KhnvvG?A1j*hZnJZ9Y0jlfjX>a&JTz5E`;59NkhL<>DUZ6Iq+WRAPnZXV_M zAtkttO)2_&?lWT?im6=u>Xs_tS0x1U<}gu*@&>6#ii>U(@)hxNfYzh?-2 ze%(eSP{AHPoo)+2&Hsp|QXO$iRbS=pu@v9Gp*oJE%`>cDE`(q36ZX|}UVl=kczcCS ziW|W3G5Q3-cxD}3Si!h_aHYfFQo%11ZXe28gE)vaK#hm2Y}Xt1;7u*hTLVcSzgp;9 zqGinbx_Cnk(n5j~jR&`{#FHd+u!rBn_{FY>Wmg`>3sH*WzzhPQd4MC_0^b6Dy~tfn zVO%aPqcA}L=DMqaUzK{j(pS6;*g~JPz$PtBLWxd7E3cGA{Ni|T=lJTk?vJbIu-u`a zTAhRqkhtLfs4?qp5s~0u-GiwJa3|`Fz>ms!^UU>!dnh($wIRNNONY9+*hBR@Fb+<# z&C@S;_AZZm#u45J|5_Q{hnCT_*V!R75LR=hvzioN+|>Oa+uajitX%@hYnN5iic?~n54 zCp2sE5Qeu1r*KaU-0lT9Avv#cP)9;V6Yynp`5c{N= zO)p0Ji7?zbn6BV{G|FQ|+{s8gFt1s7`~$eR`;9jQ#PUijyij~Uu9 z=EApdK}cqCB0N^aFT@6^Ic5C`u!$Az#vXCCv)+bxF)jZEA4!UTbI>LU=ftLg=o(?& zf_>=lr}Fjl$|9i^O<6(2*%ac3SV14Z@^*~56*`|o+AAcUblXma(^gA?f9YRIr1OgQz4!f}o z3YbycH3SP;j33hZAm@oz0GCY=F$OaDy-q29;a)ze>B$0l#ExfU8DjxG-QAW&fXgo8 z7u;{Y_kii-64&fawtUL!inujp_=PseNW#`_bTO`_l@+p2?vzzd0lyM~g~ZoxAOv?g zgn2ph&#Eu&-l7_ss><#^e3Ie{ERwGmXk-4>B*8BZ)|BAaK00Lswhm(E5$1Kn2#3md zIA577#V@|?r$!mKBmT4GSZI;aOi!vM6iXX^{E+j@sGsi@^&E0PYThNbIU8VjfM0(6 z@Y}$zc{yb0exJUf=A8il`hD7<{vh{}wW1h5ggJHUKS{L?tCb7ven$0o-*)mN4&I~p zyuLpQhu&(^##%U3*TiFv@rUBRv1?RKqOAT9UegS{{X_>WnW0R+J#WS|{A!c;q^@HA z1t;NK#vOtg8BN14M|RuTKYf@41j?|H(j7gqGW_~cuu;}$@%no~_HRj5-cB1ET6!)k z!7oI6uyTjuikwY`EZ{}SoJ7QrpdTJ6}Y*x_aOA7&IN*QO-b zA66665bi{KIHqm&UkOum14ymEqL)$5kGMOY>j2J#Q7bX%O{? z6jIh2XG~7VuVF?jzJFtrgM#XWSnAw&({%jGP@1At9f&CPAlr>kiLI2*RYgTf{l;D| zj4&q%Hw@QqL@tB>)sU?!!>?0nF`olk2Hy1XlXKQx@+sUO_0@E98GeDD9K3{a`CZZe za;rUSf*R>B6`a64e#we+Htb=#X07q3bVyy3Ln7=iyH=~t1m5h&4|mW3dH@u7Q+;B6 zeZv?69ap;uBuY~j>gR3RfoNgFK-C&?D|B$)L2FI*4niAYmfe52FB?gi^?i^ z@ZK(G@LdJFkuKnu0)8P+BtzL*Q-L=~ANz{i@0kFO$wK^aJ71j@FF zhJpQVtE!nSj~_-*v4A-C_n}`_CW%6hjd1?i`;v?oUi>iaL`^t+Y&Wd<3}P=uE}%mE zkogy)@h-wg9IHebWX6D<2N%XZbd3Uj1sJVXyGE8_%MJIyFv89g7+C?obp6I+C;X<- zMj&D?>TQ+*sqwnMiSOLu=9^OEkA|>4D8~FVp;xckIfV~DeOIFEQ=+e04zT` zU&Jruzi6jvG5>muzTzUJ(?XkY5eH(YW%V0vTaoRG0GF>l82ZSpD3C}Gumr!}rOw>y z4AU++imS5#vPpu!0fX=Phq%8N|GX^-cg0cfIvpc$q@x7=;u*^Z9iC_AUr$iPu_na= zdMw?VtxgFGiq;5VEyfR5p{ttOSJ56B%MC8Mq1xSwaY51i{1+&UdZ0JYznYIPoD$3A zU#kWV%8eEH7ndEzdHX>Kw!6Tukj&Br^&4hq7G;OOb@a7ScN#CtUtf5Cl+(6%#xU5H zrjzac;FSsy#j^a@9usPQ4g6Kk7u57t*TLZHj94jtAytJFG#!c$GDpWi#5j8%w>WW%$)LG$XwN%fxgE6e2JAVB<^RLG#tgKx1l!Viz z`g2ia#2}ROFT~kWjq}y%pd+zNCjexcxs>F;P@Cbx_iLg3iG|=+2nm7<%pKif;e(Ny%+Cm&FfvO9$t_L@>A;v@2SV_w<>uE(`HP&p*uPzqsav`Nc9P zqz^i!QAl4BKLj?p2i(;=jL{%mtlmH7MA$|0UqGvH%HXhJ=UR;G1$u_sZiAi{;)nYF z-u(G5@ULYxYzh!jv|$s}Q$ZV&?8Pm z%Hk_59;Vol>Ry3bbnHW*c}e}od3X15+!{330soo|-Ga38LA85&{l;39$Ud?ewMN|? z>W}X>5I^*oW*PrN*pSNrU=MS#H;gw?hrgH;D<$~FwS~GrD3s!BqmHQ!^fB&F9#aVT zwTBuM##QGa^{lFUYA3}8WTnx@g+alO$G>o-G+rH`47|E(Q#=j)YGT_m7S#TszW(g>YxI;gVj~_gG2(OH&vD3!tw+ku`gtoKX33*E9pOrg{)U0~^A6h-_(n}fNx;@wbxkhRg>fCFYdQZ_%D)s!Kqo!7&^7N7xCpUN=f85^JoEig+(XQ~ zN&Bz_Q6?;D@Gm?$?)itvf7zOHX81h{{40sm+ux_JaQ>?dzYyhPIG$2V+|Yx@0_QcS z<4rs%!7qj_j5MF%o9I7IuYA2TjRBV7SDa~1)Zsi)co!56`LCdUkKR9C{1EqIy(tz( z`g(UBNANSCtgNn$FR9;P{W3dhO>DWy*o|`{hC==;5S@l!8m*S8fz$)J&9_v~HSbO} zPhNmu`r1PpvjJqaz^{WgDojf1HxAG{^n{Bn-Z6F7gRQf-T=f3KV_}?CqzQ~GG@Qe^ z>_D4@SLyRF9p4zS?n)k`0lLbCTZoGbI0(=AuLQ<{_#yMJ=9AW+}yC|J`KP0&YYlrY~yHq@@T^znRvm9ca`85PWm%iP2qNyht;ZGsMk8Ta&dY(erdE~ zAX|p}Hz+5k;^p=8Y*#faX`-Lxs$^=v6 zav6R>n+63ah;kMJwj3G^e3YuD;TNdO*{R)$|(;~|3fy)dxm zv8JmV?xl~)s%iLzIBlx2iC$AWA2-iD>~^d}pZ)V+yD%A9L@d251xDuAZ!mtLLi<{rPuc7` z$IP~BzR4$)h21E{FKRx5FhZOLOwNDRX3cH1z$wSCcU1diti5`!_-C~!7cz|z@j_pF zQ>?UpgVE|Gl+E)#L?JzDCA^H7&%Zc+i1W*gR&4_DC?_=0c!ok>@7#6Cbo_Ghb@mS% z#-gY#3~sQSSC!Xq@Cj?QL7%CSmU8{!hMCRFp@Zf4GL~V>U&Jr? z;Xo^tu_6EEBJBJN`{`82U9f(B{RZO~y!X9eTRbk*0FQ|&)q*N7JSo91*vv<9g&@Dd~I(yPs9j)o{nEr%w<&PSZu;r zD)mM5)A4Hr)f#8JA4|5Jx?#AhA-P$#Oy^&?HJZEH=K`80JVjjhF>ur&bv6n8;e_=4igQmMHzlw>#m+e8;oo8lBvcqk;mmS{OWM$;638$ znH_Fy*oq4OJr3J&#;?BxJwboY!lh|BcJF~?bl@egKV|r(aT#i*?l@*P0ig5aD&t=< zu&v5h~lA3?vf_=)5s~o=&W-)fS8z`pgCnHOtXgZr*j$i1r zz_n56s(Gupj4pEjp}=~@5kb43Vy|MNqHccdCHTb|1Vl3?5I^i3j7`j1R?9@}qWI;~ z5Vg~mq~+h0H!c4)CuNM&;WX_0w=Qdv7vo?2_d#%N6b|_J{_YOre;|lDoqwTp9I#ah z*rLd1qp9RB2)fOof_~-mUv}kF0miSYx@x|QNf)J;@UMLob4;8JBG8Hk@QVk{{6Qzb zeuMF=h3gN05j;&#^n{PC_@8X~C7w*ne}(k8s55az)>xu0ieK6k5TE~w4layfqEOQ{ z9lscxMuEA=*$t0Wq#?)>{F=%2^IU%@M)_L);}Dvh@8!o{%D;5=$hbf^dheat|Iq@T zmg5(X!sB0Cwi_3XAF|u5U?Il>?ZMc`XJae z{JO(4ardj(R5Wr|OMQNimEu>h8T%P-*ao=7Q2>XN-_Ird3-`}Y0j| z4XVCP%w)j@HkI%%PK|M&1JFS-b6a}~I#`BZ+P0hw^c%5#3m+0|C_nZx`~tr~tclg! z4E@kZu;9*^hF`EG+GbL_-I{LvPGMZr@GHbN^Jh3x8p|3@4i_Q<3(D~e_ORHMo;!x`EfbA4rm1&i?y z|Kc7Zj0h)Ch22K~AefI|uh7xdCwfC~8tuGH!O)1Yh|a+SDaH?7TbqJ0^Wo&Y#O8rm zoq2b%A&c|Nj9-(UpDj+yskub``@ITKDGB5y8yi8l-UYuBgYV!60~wV8)Z zQ6w@zLQCU^H2V^UGJgz)`F%2uZHrfPTGM$oYQT0slIVZ1N0Z*y{dT^<30%%wx>W zdGQUd-*_w$%UOR1-xyT;AFO(f}wS1kJ$5`+s+`nhiSEGMFh-p6z9K=ub+-zd}OjC z5q{ZthhYo#hy5qg4Q6#;89eoL|PD{Svde&r$=~Mx`T)h5Eyp1GE9xHFsxmoh)isaOKFz zQQA15XRH`M6dPsRn$UJ@KDvQFq_ShyxHt&@zQyNXy8ci--rZVfj3+U!Q5?qnmAbHg zgQJDOuSFhgtv7t1qy)e6(ZZ$hZCX;+KZ;*!MAP+$lE=<}KSft-EcM*N5vbL(4qHD6 zK7PUbl54nHV=32fbRpk#jEf?8KbPRwb81fx)f)QR4X(S$-`@-V#b09l8WI|<(#9B< z9c~Km?4L*%@XON+_onNwk#Vx1yY3fhu zu^%h&uOHBvEba`*H2y-s9%jM^R=g3}th7zYe=CJR%o&NeXxhLb6#f%Ye*=FbKdwA} zA^(MHd7NLKy!`3}U@L{o1m0A6-#8ybQ^9rgxNJ-zOa3udne8_wYjgC80yfz^hg`pb zzb8dzsuspGsMQLGXVGSJ3I8%FL-4?q2r_I*%kIh_3ikPzm;V|js6&wLJW>g>a<~gh zk1J>N@V5%*mqEKuaoCU`T!>#Nvxy`B1^%Tt-dpn)5@GK}OYw{AH=gK4o@iK{mwbL1 ziLjmYqXgp@u2#_c<;4#O-@kq2G3vH@#v|D&ra*oXFdny0Q=)aaSm-4i0uFQA7B>x2u*#ooL2dwu+xgC~t?aG4PCe%_3v676xcKURWY@8lNc zYR=*Br)b*sHRCdRC%t?6{k;;fwb$T)8&qbm@pJWVkJg>i{Fe*scQ&8@3ZI?TN%)Ik zj9(@BFZ}&4X-y)2sMTr`{lSwG{Nnr<#}A={`8Hfkm48ykzp#SdkhNM>!2am5m+-Ii zgw>fu{80CK(rSiH&~~gWeuyRTZCwekEaP9DYl}8>(l{fh-yd}co57{NecqfAPpg+a zeo>PDLL23`fxt0F%|XiJhlFvl&D3j}LjWhui(8ie!k-JAY|O94B=UOC!Gpyp+yZ`S z^G>CGo{nGi)N-R&zHDC;tU2fl0e4zKGc{I{ z5&=hbNvLN&a60Uxt3ghaUHg2APc%Pn$l0GN;>YeM&naN;5 zpsV|8oa?)1s+nGYo=Q~Q68Ic_R?RL7fqMOQ`cAA*>`K=ztqn@ zRB@-eHSu`}m)zNROX7FxXBTwmy6cTQ)ys)%>T3>Z;lDsYvEs{#|5;z-=ErrN_a6S| z`h}mb|LmdQBDE^<8N6qvx93R|^~+bZ-T~9O)C?+bdWb3mYt$`?OY1A{&I^INgZ$)k z^%aFS*U5_Bz^(Lon(b=gGgJqGcu)J^x~_{7s@|zI1IZErtAi(nwYaV;=wJoAOgmW= zBHoi?8S=^vB2 z$kyu10ga;R%u~T+=Nguz)xhMky!!(c~H0{j}C63 zO=ErcA$!rlJ!|qpXicLn-P-uTJq?8>)OmjO`F}Zo>il~b3Vxgah!A_pTJq!@nLT%~ zF!D^P;Q#Z*?W>-f_15Uo-)LcRso=Ny#9w~uXZJrc{>Et*wq7%S@99sh>pnDV_xQ;_ z^VgJ>0N<2>UW%( zV;2bix8C#Gi3AmrQhT!_m)K+hg2tk?fuza+-KM%5>v zO?O`)D6cms=9A$9&e66Rwz4nfsmiW9)jjeo%}d>f#BxfLlv}0hI;T97oNI67%6;fMKE!&K7M^@X8#3( z%FkgyG8|vTu4t2^UnB$F49ASZ8kfriRrr=%*)tQqL15-Zgu;4F_r;34AmF_Q|9=`T z`v6_UWqIB28lRCbWIuLw&4q$2jH~+s2=GC{EqsjOxVC`HWy118lmAC?xg3rQ0R6xG zZ(Rt-g(vU%ZOU-j2WTz$Z3Is9Q&d*lWx~N_ZGI@VhG;P`|d#AoPL|>@9|$4;SJ0`=KJpD z#ZIwJ^?-PQhU7x~LZSGcqFtYE^1V-S#|ravp-^~_O_#(2JR5V|Qi1r%h=&*#eGmTl zA(>yrpYqCoj61KUscMj)NPm9Na(WByA!bneZvi1Gys-FRR10?)*ewOqcz&{7{!KW(xkl)pvh!-dBi|6X0zUr>;-FZ=(-?@!<@7 zI0GNfz=t#N;S78@10T-7f8rU?{t_G}_)GFX@icrm^bcp?!x{K+20omD4`<-R8Td~+ p1Bl`yjrKz`P741eMD=CWe`G51?JMHA3xwNy?>SgZOXXkke*p-x>z)7r diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index c04ade80..0768c29d 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -50,12 +50,38 @@ begin else if(~(| adc_d[7:5])) after_hysteresis = 1'b0; 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 -reg [6:0] ssp_clk_divider; +reg [10:0] ssp_clk_divider; + always @(posedge adc_clk) ssp_clk_divider <= (ssp_clk_divider + 1); -assign ssp_clk = ssp_clk_divider[4]; + +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 + 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 + 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 +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. @@ -69,12 +95,13 @@ reg [2:0] ssp_frame_divider_from_arm; 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; @@ -90,7 +117,7 @@ always @(mod_type or ssp_clk or ssp_dout) 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 - else if(mod_type == 3'b100) + else if(mod_type == 3'b100 || mod_type == 3'b101) modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off else modulating_carrier <= 1'b0; // yet unused @@ -106,7 +133,7 @@ assign pwr_oe4 = modulating_carrier; // This one is always on, so that we can watch the carrier. assign pwr_oe3 = 1'b0; -assign dbg = after_hysteresis; +assign dbg = modulating_carrier; //reg dbg; //always @(ssp_dout) // dbg <= ssp_dout; From 7b941c8d7f8d8203316fdfaf1ad0038fc4864cf1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 15:27:44 +0100 Subject: [PATCH 11/18] Fixed memory corruption after reader-attack in armsrc, fixed annoying LED --- armsrc/iclass.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 329e1765..72cfbefc 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -998,7 +998,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain else if(simType == 2) { - uint8_t mac_responses[64] = { 0 }; + uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 }; 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 @@ -1248,6 +1248,8 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader //Dbprintf("%x", cmdsRecvd); LED_A_OFF(); LED_B_OFF(); + LED_C_OFF(); + if(buttonPressed) { DbpString("Button pressed"); From 09b69422e221428d7e4870ae413fdda9042eac5f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 15:29:03 +0100 Subject: [PATCH 12/18] This was resynthezised along with my hf-changes. Nothing changed though --- fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index e942921a8685731cbcf0e7bb6f86a11ea629dd0c..51b0681cd6a082550a19dccd794ff40439e393f9 100644 GIT binary patch literal 42175 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 literal 42175 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�$DR4HSsNmqcrsV|eYUj>P75ugYUv3T z0}=m;-=;%P_r$E#h6&3b2vR-q=TH(U&c=2l5L%eU;fY1+gEdXdb=EvXAM%AG6)lc> z;ey=a|Rb(9XMEc|E@P-?V8$!BA%|tM+4n5OTXI*E^?JWsQd#bI~ zou#p7^qV4|ppVP>nF?Q^x`^N>w!dDLkyWxQQ(IRtU7*sqNZOWZ=py0@wIZU+kJOu; zy5Hu>>$H!`4E$dg6cAlh;+;+ViQ*AJ)x38VIwzC%*1nd!2TxJej$=uKK7F zeh)%~pZxc_4>)t(dA@eqdp>@2{;hHyzuB4V>KBP=YSkOD`ay{eUAnI!s*Kz$>oOPB zReTx3O-iU>;S+W9{WjOydUxbg^oKOxsbJw_WI~{Icv369@4B{wGP2I9G$Or9P#ZRb z^}-YB_qjv2@T9{qdzGLT&cX`fNvTZ*w8>gy%oi-AKOURk5wQ>7Xz4};`Qy?eUCxc^ z`LT-CAwk|~%{MCSh&M2J^5m*73sAIGtY7MhKlE!m1W9RGh9OwUSxFXp2Kb5pUDvXH z-K6vjD&q>X{3qVHp0qVzn*sri`3Oa|B>$tQBQaWysVfQH(06{~H&ObPVQupDt3Zut zqn>z;Dk6*RbzSpn^(Or%fuL`6)Dv0yE^u{Qz`9`j zsz6?r8exOf6R(l6<}-8aZtKL88~KUfgsLJ!+Bq|+y8@v)2TzEf1Z`s4$LP3oRl0he z66(_igh)R>vHeDdf`9-ESeWIZgX6bpsOvmxF7DrcvnRxEZZK`9Cf&ci-fu$f=hvVA zm-DC2zcXD3+WdQj)Q_Xfj=Y*bxQT_K?}dfn*O#=edv@NN!=tY&VM$mB+FbLcKltfg z50AZinuVQLkKJ+ln$4X@=j|Vx_(ISoBD(Fn%`5cThc6InXFGl)UE#6|#{lTC5VR39 z*$o$|rT-oZ!Dtz<)&XI?j{#g>063mIGEH#&Ht+f#Mr!Y4_;4KHvL|G4_SO3=)UWTU z$*tKpce>!e#fiam)jAdF$hv8Q?Lsazj~JH$#}^8)ENS&7!wJ;J)fVVaNeJ5L8F&}h z0fnavZW}XViwtt!m(y%HP3UzyZC^VhF1rBjxc1OS(*TaA3+hESI+zBUYdF9#O>k5b z;_sS{r`{9keOF{ATy`B3SQ7Q=iu|Vc_}^vgU6ES4mgY_uI^6H-q)J*P&5T|bnJ&1m zp-y1j1-Kjlv~M?T;OPvw>>{=8VM^pW{nnlZnGe^^JvvQrygo;+6SvB{Ggs8jJ~~bC z+H_6FTB43^+NVh+9ZARZ5xr9C}=N6|4{@%cPmEm##(2UFO zdu*&%87>C^&A9Bf!QQZYOyKfdF-;(UTpD#bwdsmjWc4(Gl?osBaKpH){A>S-`&GOT z%WydW=nyX3I9B=Y`sMZcH|dx3+F%ZsN9NFKX%?pm-W+zp79b14(eT651jl<1Rgk)| zx|W`tCJg!CwOY>{u1jARo7*={klq|dY$`J+!UJg6z^E75kxqtVMq!1^WrFm-%LXpj z>eoi*&LH^f74pTxYu*de;T(z`%x?ua`VvhFPuz=yX z#>eF{VO7wd>2Mr83EKR7gz0eXKlz`*uTO_#|H(T+n=)Ju09pw_8_`d=ip8!nU7-WQ zhg0_;5i(mTh1;$ia#lfKW?|!z9VxXj`UOte+c@>6gboPbP1MtNJPE#Q2I!i_%jqeg z+fLGjn=Gqagew{R*MtDAdU|8?ZA2kcNN^GsZO0SuO=#op+_LYx+#tEcDz&NV z7x&OUd!bnpzMI&uo|N8Gvg^LdpS29OA0$2K5BVjWC1KX`x$Nee{(CU1>BuPkB`t7# zp|B=~C#z_|kc$`?;Pm%=*j#Lc-a|8ts^(gPIV;T%x;1T{&3-gcQ{r{nH?ZD6`9Jv6 zCEk#DO=kZ1WA=aA+UiTC|E47)GFrytrH2R@B2 zpR}Jpf8Jqfx}bhO^N-rk|F!#Dzp;(?=KoLHT%gN=QbP#(GlLHD?j^(zN^Sf-rpk?Z zYX#a}YEy0#${f?6(X>6L?ge43^gc6bAk-oFJ#IFmE=yq%zsJ{|8FkrvQ_!ZQ!qb#G zXj2NJOjGKh%?vu|&zRq423-!6`ZwwF1@DgT|2z0WSnwLnpv$FSe|KFj zwQ;4HbUA4A8+18n^PUUSRXBJOd{^*fy6~U2P0+D-71B6U!rLuP9UpnuM!);P?`Gh4 zGw{0^_}vWrZU%lg1HYSr{~ynQ@|WN+!C$gxoCb{?CuW3lIy1KVtq<`UjbgZ*=eM@} z%?(7v?v=HrSk`ZD{q8?SfA~HB;r`HnviVW{L23KDkNn^F6CRe6eve-C9_*j@YFzKt z{=s{Ae*VLH@m}qp_iBFrQ@-at*gx3Mzq3ETLG|CO`FXGQ&wn=i^Ipx*du4ynpWorv vZ{E-UukkC5BY4QEz!#GEFX7OMjgs5n{_)yZr14i=xwZSA!=<#8_lo}qj5k?J From 6b038d192a8418ec7c5ab74c344b4d4b216efc5e Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 15:45:54 +0100 Subject: [PATCH 13/18] Minor dox --- armsrc/iclass.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 72cfbefc..e7dd9535 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -921,7 +921,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 inptu to the FPGA becomes an unmodulated time of 18.88us * - * In thist mode the SOF can be written as 00011101 = 0x1D + * In this mode the SOF can be written as 00011101 = 0x1D * The EOF can be written as 10111000 = 0xb8 * A logic 1 is 01 * A logic 0 is 10 @@ -1215,12 +1215,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader cmdsRecvd++; } /** - After changes to parity calculation - Time between reader EOT and pm3 SOF - delay 21 -> 480uS - delay 10 -> 220us - delay 16 -> 388us - A legit tag has about 380us. + A legit tag has about 380us delay between reader EOT and tag SOF. **/ if(modulated_response_size > 0) { SendIClassAnswer(modulated_response, modulated_response_size, 1); From 758f1fd1f37d52678af1e9b1f72d58aecf41cac4 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 16:07:58 +0100 Subject: [PATCH 14/18] Fixed issue #43 on github --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index cf55e606..d326be2c 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1772,7 +1772,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u 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 & 0xf8] |= UIDbit << (uid_resp_bits % 8); + 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++; From d60418a05f2cbaa97140c569ba63f1a1eb831a79 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 16:28:28 +0100 Subject: [PATCH 15/18] Synchronized loclass library, imported the legal warning --- client/loclass/cipher.c | 20 +++++++++-- client/loclass/cipher.h | 20 +++++++++-- client/loclass/cipherutils.c | 19 +++++++++-- client/loclass/cipherutils.h | 20 +++++++++-- client/loclass/elite_crack.c | 62 +++++++++++++++++++++++++++++++++-- client/loclass/elite_crack.h | 39 ++++++++++++++++++++++ client/loclass/fileutils.c | 43 ++++++++++++++++++++++-- client/loclass/fileutils.h | 38 +++++++++++++++++++++ client/loclass/ikeys.c | 24 ++++++++++---- client/loclass/ikeys.h | 38 +++++++++++++++++++++ client/loclass/loclass_main.h | 4 +++ client/loclass/main.c | 40 +++++++++++++++++++--- 12 files changed, 342 insertions(+), 25 deletions(-) create mode 100644 client/loclass/loclass_main.h diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 463ba9be..d3b1e799 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -1,5 +1,17 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by @@ -18,9 +30,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ + #include "cipher.h" #include "cipherutils.h" #include diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index 4bfbe0b7..176a2976 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -1,5 +1,17 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by @@ -18,9 +30,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ + #ifndef CIPHER_H #define CIPHER_H #include diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index e11e8d22..f9c62273 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -1,5 +1,17 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by @@ -18,7 +30,10 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ #include diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index acf96115..cb090f69 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -1,5 +1,17 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by @@ -18,9 +30,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ + #ifndef CIPHERUTILS_H #define CIPHERUTILS_H #include diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index adedba85..a8ab869e 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -1,3 +1,41 @@ +/***************************************************************************** + * 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 file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * 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. + * + * This file 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 loclass. If not, see . + * + * + * + ****************************************************************************/ + #include #include #include @@ -514,6 +552,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) */ int bruteforceFile(const char *filename, uint16_t keytable[]) { + FILE *f = fopen(filename, "rb"); if(!f) { prnlog("Failed to read from file '%s'", filename); @@ -621,6 +660,21 @@ int _test_iclass_key_permutation() prnlog("[+] Iclass key permutation OK!"); return 0; } +int _testHash1() +{ + uint8_t csn[8]= {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0}; + uint8_t k[8] = {0}; + hash1(csn, k); + uint8_t expected[8] = {0x7E,0x72,0x2F,0x40,0x2D,0x02,0x51,0x42}; + if(memcmp(k,expected,8) != 0) + { + prnlog("Error with hash1!"); + printarr("calculated", k, 8); + printarr("expected", expected, 8); + return 1; + } + return 0; +} int testElite() { @@ -653,11 +707,13 @@ int testElite() prnlog("[+] Hash2 looks fine..."); } - prnlog("[+] Testing key diversification ..."); - int errors = 0 ; - errors +=_test_iclass_key_permutation(); + prnlog("[+] Testing hash1..."); + errors += _testHash1(); + prnlog("[+] Testing key diversification ..."); + errors +=_test_iclass_key_permutation(); errors += _testBruteforce(); + return errors; } diff --git a/client/loclass/elite_crack.h b/client/loclass/elite_crack.h index 21004e59..fb27355f 100644 --- a/client/loclass/elite_crack.h +++ b/client/loclass/elite_crack.h @@ -1,3 +1,42 @@ +/***************************************************************************** + * 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 file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * 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. + * + * This file 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 loclass. If not, see . + * + * + * + ****************************************************************************/ + + #ifndef ELITE_CRACK_H #define ELITE_CRACK_H void permutekey(uint8_t key[8], uint8_t dest[8]); diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 206d9695..4079dccf 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -1,3 +1,41 @@ +/***************************************************************************** + * 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 file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * 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. + * + * This file 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 loclass. If not, see . + * + * + * + ****************************************************************************/ + #include #include #include @@ -40,14 +78,13 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si /*Opening file for writing in binary mode*/ FILE *fileHandle=fopen(fileName,"wb"); if(!fileHandle) { - PrintAndLog("Failed to write to file '%s'", fileName); + prnlog("Failed to write to file '%s'", fileName); free(fileName); return 1; } fwrite(data, 1, datalen, fileHandle); fclose(fileHandle); - PrintAndLog("Saved data to '%s'", fileName); - + prnlog("Saved data to '%s'", fileName); free(fileName); return 0; diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index e02079d5..623190a6 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -1,3 +1,41 @@ +/***************************************************************************** + * 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 file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * 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. + * + * This file 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 loclass. If not, see . + * + * + * + ****************************************************************************/ + #ifndef FILEUTILS_H #define FILEUTILS_H /** diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index f7115b19..b21ecdbc 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -1,15 +1,23 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and * Milosch Meriac in the paper "Dismantling IClass". * - * This is a reference implementation of iclass key diversification. I'm sure it can be - * optimized heavily. It is written for ease of understanding and correctness, please take it - * and tweak it and make a super fast version instead, using this for testing and verification. - * Copyright (C) 2014 Martin Holst Swende * * This is free software: you can redistribute it and/or modify @@ -22,8 +30,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ + /** diff --git a/client/loclass/ikeys.h b/client/loclass/ikeys.h index 1de46b62..13096194 100644 --- a/client/loclass/ikeys.h +++ b/client/loclass/ikeys.h @@ -1,3 +1,41 @@ +/***************************************************************************** + * 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 file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * 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. + * + * This file 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 loclass. If not, see . + * + * + * + ****************************************************************************/ + #ifndef IKEYS_H #define IKEYS_H diff --git a/client/loclass/loclass_main.h b/client/loclass/loclass_main.h new file mode 100644 index 00000000..b6d58a8b --- /dev/null +++ b/client/loclass/loclass_main.h @@ -0,0 +1,4 @@ +#ifndef LOCLASS_MAIN_H +#define LOCLASS_MAIN_H + +#endif // LOCLASS_MAIN_H diff --git a/client/loclass/main.c b/client/loclass/main.c index 42019072..d1b0359b 100644 --- a/client/loclass/main.c +++ b/client/loclass/main.c @@ -1,5 +1,17 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * 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 file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by @@ -18,11 +30,14 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ + #include -#include #include #include #include @@ -40,11 +55,15 @@ int unitTests() errors += testMAC(); errors += doKeyTests(0); errors += testElite(); + if(errors) + { + prnlog("OBS! There were errors!!!"); + } return errors; } int showHelp() { - prnlog("Usage: iclazz [options]"); + prnlog("Usage: loclass [options]"); prnlog("Options:"); prnlog("-t Perform self-test"); prnlog("-h Show this help"); @@ -64,7 +83,18 @@ int main (int argc, char **argv) { prnlog("IClass Cipher version 1.2, Copyright (C) 2014 Martin Holst Swende\n"); prnlog("Comes with ABSOLUTELY NO WARRANTY"); - prnlog("This is free software, and you are welcome to use, abuse and repackage, please keep the credits\n"); + prnlog("Released as GPLv2\n"); + prnlog("WARNING"); + prnlog(""); + prnlog("THIS TOOL IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. "); + prnlog(""); + prnlog("USAGE OF THIS TOOL IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL "); + prnlog("PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, "); + prnlog("AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. "); + prnlog(""); + prnlog("THIS TOOL SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. "); + + char *fileName = NULL; int c; while ((c = getopt (argc, argv, "thf:")) != -1) From 49726b4088b78027b7ce3215c432cbb99a283f27 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Jan 2015 23:00:39 +0100 Subject: [PATCH 16/18] Improved 'hf list iclass' a bit, better understanding of the protocol and when to apply CRC checks --- client/cmdhf.c | 112 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 25 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 762fada4..33d01aee 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -123,14 +123,19 @@ NXP/Philips CUSTOM COMMANDS 40 = Long Range CMD (Standard ISO/TR7003:1990) */ -#define ICLASS_CMD_ACTALL 0x0A +#define ICLASS_CMD_ACTALL 0x0A #define ICLASS_CMD_READ_OR_IDENTIFY 0x0C -#define ICLASS_CMD_SELECT 0x81 -#define ICLASS_CMD_PAGESEL 0x84 -#define ICLASS_CMD_READCHECK 0x88 -#define ICLASS_CMD_CHECK 0x05 -#define ICLASS_CMD_SOF 0x0F -#define ICLASS_CMD_HALT 0x00 +#define ICLASS_CMD_SELECT 0x81 +#define ICLASS_CMD_PAGESEL 0x84 +#define ICLASS_CMD_READCHECK_KD 0x88 +#define ICLASS_CMD_READCHECK_KC 0x18 +#define ICLASS_CMD_CHECK 0x05 +#define ICLASS_CMD_DETECT 0x0F +#define ICLASS_CMD_HALT 0x00 +#define ICLASS_CMD_UPDATE 0x87 +#define ICLASS_CMD_ACT 0x8E +#define ICLASS_CMD_READ4 0x06 + #define ISO14443_CMD_REQA 0x26 #define ISO14443_CMD_READBLOCK 0x30 @@ -235,11 +240,15 @@ void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) break; } case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break; - case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break; - case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break; + case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL(%d)", cmd[1]); break; + case ICLASS_CMD_READCHECK_KC:snprintf(exp,size,"READCHECK[Kc](%d)", cmd[1]); break; + case ICLASS_CMD_READCHECK_KD:snprintf(exp,size,"READCHECK[Kd](%d)", cmd[1]); break; case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break; - case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break; + case ICLASS_CMD_DETECT: snprintf(exp,size,"DETECT"); break; case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break; + case ICLASS_CMD_UPDATE: snprintf(exp,size,"UPDATE(%d)",cmd[1]); break; + case ICLASS_CMD_ACT: snprintf(exp,size,"ACT"); break; + case ICLASS_CMD_READ4: snprintf(exp,size,"READ4(%d)",cmd[1]); break; default: snprintf(exp,size,"?"); break; } return; @@ -276,6 +285,66 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } } } +/** + * @brief iclass_CRC_Ok Checks CRC in command or response + * @param isResponse + * @param data + * @param len + * @return 0 : CRC-command, CRC not ok + * 1 : CRC-command, CRC ok + * 2 : Not crc-command + */ +uint8_t iclass_CRC_Ok(bool isResponse, uint8_t* data, uint8_t len) +{ + if(len < 4) return 2;//CRC commands (and responses) are all at least 4 bytes + + uint8_t b1, b2; + + if(!isResponse)//Commands to tag + { + /** + These commands should have CRC. Total length leftmost + 4 READ + 4 READ4 + 12 UPDATE - unsecured, ends with CRC16 + 14 UPDATE - secured, ends with signature instead + 4 PAGESEL + **/ + if(len == 4 || len == 12)//Covers three of them + { + //Don't include the command byte + ComputeCrc14443(CRC_ICLASS, (data+1), len-3, &b1, &b2); + return b1 == data[len -2] && b2 == data[len-1]; + } + return 2; + }else{ + /** + These tag responses should have CRC. Total length leftmost + + 10 READ data[8] crc[2] + 34 READ4 data[32]crc[2] + 10 UPDATE data[8] crc[2] + 10 SELECT csn[8] crc[2] + 10 IDENTIFY asnb[8] crc[2] + 10 PAGESEL block1[8] crc[2] + 10 DETECT csn[8] crc[2] + + These should not + + 4 CHECK chip_response[4] + 8 READCHECK data[8] + 1 ACTALL sof[1] + 1 ACT sof[1] + + In conclusion, without looking at the command; any response + of length 10 or 34 should have CRC + **/ + if(len != 10 && len != 34) return true; + + ComputeCrc14443(CRC_ICLASS, data, len-2, &b1, &b2); + return b1 == data[len -2] && b2 == data[len-1]; + } +} uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool showWaitCycles) { @@ -332,24 +401,14 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho } } //--- Draw the CRC column - bool crcError = false; + uint8_t crcStatus = 2; if (data_len > 2) { uint8_t b1, b2; if(iclass) { - if(!isResponse && data_len == 4 ) { - // Rough guess that this is a command from the reader - // For iClass the command byte is not part of the CRC - ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2); - } else { - // For other data.. CRC might not be applicable (UPDATE commands etc.) - ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2); - } - - if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { - crcError = true; - } + //The following commands have crc + crcStatus = iclass_CRC_Ok(isResponse, frame, data_len); }else{//Iso 14443a @@ -358,12 +417,15 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { if(!(isResponse & (data_len < 6))) { - crcError = true; + crcStatus = 0; } } } } - char *crc = crcError ? "!crc" :" "; + //0 CRC-command, CRC not ok + //1 CRC-command, CRC ok + //2 Not crc-command + char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " ")); EndOfTransmissionTimestamp = timestamp + duration; From 41fdd0f061ae7ef4cdc5bfc027f1097c990c3318 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 16 Jan 2015 22:41:19 +0100 Subject: [PATCH 17/18] First stab at adding 'hf list 14b' and 'hf list raw' --- client/cmdhf.c | 112 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 29 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 33d01aee..20ca057b 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -137,14 +137,14 @@ NXP/Philips CUSTOM COMMANDS #define ICLASS_CMD_READ4 0x06 -#define ISO14443_CMD_REQA 0x26 -#define ISO14443_CMD_READBLOCK 0x30 -#define ISO14443_CMD_WUPA 0x52 -#define ISO14443_CMD_ANTICOLL_OR_SELECT 0x93 -#define ISO14443_CMD_ANTICOLL_OR_SELECT_2 0x95 -#define ISO14443_CMD_WRITEBLOCK 0xA0 // or 0xA2 ? -#define ISO14443_CMD_HALT 0x50 -#define ISO14443_CMD_RATS 0xE0 +#define ISO14443A_CMD_REQA 0x26 +#define ISO14443A_CMD_READBLOCK 0x30 +#define ISO14443A_CMD_WUPA 0x52 +#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93 +#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95 +#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ? +#define ISO14443A_CMD_HALT 0x50 +#define ISO14443A_CMD_RATS 0xE0 #define MIFARE_AUTH_KEYA 0x60 #define MIFARE_AUTH_KEYB 0x61 @@ -180,14 +180,17 @@ NXP/Philips CUSTOM COMMANDS #define ISO15693_READ_MULTI_SECSTATUS 0x2C +#define ISO_14443A 0 +#define ICLASS 1 +#define ISO_14443B 2 void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) { - case ISO14443_CMD_WUPA: snprintf(exp,size,"WUPA"); break; - case ISO14443_CMD_ANTICOLL_OR_SELECT:{ + case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break; + case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) if(cmd[2] == 0x70) @@ -198,7 +201,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"ANTICOLL"); break; } } - case ISO14443_CMD_ANTICOLL_OR_SELECT_2:{ + case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:{ //95 20 = Anticollision of cascade level2 //95 70 = Select of cascade level2 if(cmd[2] == 0x70) @@ -209,11 +212,11 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"ANTICOLL-2"); break; } } - case ISO14443_CMD_REQA: snprintf(exp,size,"REQA"); break; - case ISO14443_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; - case ISO14443_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; - case ISO14443_CMD_HALT: snprintf(exp,size,"HALT"); break; - case ISO14443_CMD_RATS: snprintf(exp,size,"RATS"); break; + 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"); break; + case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); 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; @@ -281,10 +284,44 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) case ISO15693_LOCK_DSFID :snprintf(exp, size, "LOCK_DSFID");break; case ISO15693_GET_SYSTEM_INFO :snprintf(exp, size, "GET_SYSTEM_INFO");break; case ISO15693_READ_MULTI_SECSTATUS :snprintf(exp, size, "READ_MULTI_SECSTATUS");break; - default: snprintf(exp,size,"?"); break; + default: snprintf(exp,size,"?"); break; } } } +void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]){ + case ISO14443B_REQB : snprintf(exp,size,"REQB");break; + case ISO14443B_ATTRIB : snprintf(exp,size,"ATTRIB");break; + case ISO14443B_HALT : snprintf(exp,size,"HALT");break; + default: snprintf(exp,size ,"?");break; + } + +} + +/** + * @brief iso14443B_CRC_Ok Checks CRC in command or response + * @param isResponse + * @param data + * @param len + * @return 0 : CRC-command, CRC not ok + * 1 : CRC-command, CRC ok + * 2 : Not crc-command + */ + +uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len) +{ + uint8_t b1,b2; + + if(len <= 2) return 2; + + ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2); + if(b1 != data[len-2] || b2 != data[len-1]) { + return 0; + } + return 1; +} + /** * @brief iclass_CRC_Ok Checks CRC in command or response * @param isResponse @@ -294,7 +331,7 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) * 1 : CRC-command, CRC ok * 2 : Not crc-command */ -uint8_t iclass_CRC_Ok(bool isResponse, uint8_t* data, uint8_t len) +uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len) { if(len < 4) return 2;//CRC commands (and responses) are all at least 4 bytes @@ -346,7 +383,7 @@ uint8_t iclass_CRC_Ok(bool isResponse, uint8_t* data, uint8_t len) } } -uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool showWaitCycles) +uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, bool showWaitCycles) { bool isResponse; uint16_t duration, data_len,parity_len; @@ -405,12 +442,15 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho if (data_len > 2) { uint8_t b1, b2; - if(iclass) + if(protocol == ICLASS) { - //The following commands have crc - crcStatus = iclass_CRC_Ok(isResponse, frame, data_len); + crcStatus = iclass_CRC_check(isResponse, frame, data_len); - }else{//Iso 14443a + }else if (protocol == ISO_14443B) + { + crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); + } + else if (protocol == ISO_14443A){//Iso 14443a ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); @@ -431,10 +471,12 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho if(!isResponse) { - if(iclass) + if(protocol == ICLASS) annotateIclass(explanation,sizeof(explanation),frame,data_len); - else + else if (protocol == ISO_14443A) annotateIso14443a(explanation,sizeof(explanation),frame,data_len); + else if(protocol == ISO_14443B) + annotateIso14443b(explanation,sizeof(explanation),frame,data_len); } int num_lines = (data_len - 1)/16 + 1; @@ -477,7 +519,7 @@ int CmdHFList(const char *Cmd) int tlen = param_getstr(Cmd,0,type); char param = param_getchar(Cmd, 1); bool errors = false; - bool iclass = false; + uint8_t protocol = false; //Validate params if(tlen == 0 || (strcmp(type, "iclass") != 0 && strcmp(type,"14a") != 0)) { @@ -490,9 +532,11 @@ int CmdHFList(const char *Cmd) if (errors) { PrintAndLog("List protocol data in trace buffer."); - PrintAndLog("Usage: hf list [14a|iclass] [f]"); + PrintAndLog("Usage: hf list [14a|14b|iclass] [f]"); PrintAndLog(" 14a - interpret data as iso14443a communications"); + PrintAndLog(" 14b - interpret data as iso14443b communications"); PrintAndLog(" iclass - interpret data as iclass communications"); + PrintAndLog(" raw - just show raw data"); PrintAndLog(" f - show frame delay times as well"); PrintAndLog(""); PrintAndLog("example: hf list 14a f"); @@ -501,7 +545,17 @@ int CmdHFList(const char *Cmd) } if(strcmp(type, "iclass") == 0) { - iclass = true; + protocol = ICLASS; + }else if(strcmp(type, "14a") == 0) + { + protocol = ISO_14443A; + } + else if(strcmp(type, "14b") == 0) + { + protocol = ISO_14443B; + }else if(strcmp(type,"raw")== 0) + { + protocol = -1;//No crc, no annotations } if (param == 'f') { @@ -525,7 +579,7 @@ int CmdHFList(const char *Cmd) while(tracepos < TRACE_SIZE) { - tracepos = printTraceLine(tracepos, trace, iclass, showWaitCycles); + tracepos = printTraceLine(tracepos, trace, protocol, showWaitCycles); } return 0; } From b689b842b68c061340f18ff595ffdabf34bdc4f0 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 16 Jan 2015 22:48:30 +0100 Subject: [PATCH 18/18] Bugfix 'hf list 14b' and 'hf list raw' --- client/cmdhf.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 20ca057b..9acc9825 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -519,9 +519,9 @@ int CmdHFList(const char *Cmd) int tlen = param_getstr(Cmd,0,type); char param = param_getchar(Cmd, 1); bool errors = false; - uint8_t protocol = false; + uint8_t protocol = 0; //Validate params - if(tlen == 0 || (strcmp(type, "iclass") != 0 && strcmp(type,"14a") != 0)) + if(tlen == 0) { errors = true; } @@ -529,6 +529,25 @@ int CmdHFList(const char *Cmd) { errors = true; } + if(!errors) + { + 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,"raw")== 0) + { + protocol = -1;//No crc, no annotations + }else{ + errors = true; + } + } if (errors) { PrintAndLog("List protocol data in trace buffer."); @@ -543,20 +562,7 @@ int CmdHFList(const char *Cmd) PrintAndLog("example: hf list iclass"); return 0; } - 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,"raw")== 0) - { - protocol = -1;//No crc, no annotations - } + if (param == 'f') { showWaitCycles = true;