From 47cbb2d41851e680c84b3a7dd0465f7f7960a9ec Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Nov 2014 23:18:46 +0100 Subject: [PATCH] ADD: tnp3.lua can now validate the checkums in the dump ADD: added CRC16 CCITT functionality to LUA FIX: tnp3.lua is now correctly decryping data while dumping --- client/lualibs/utils.lua | 9 +++++ client/scripting.c | 12 +++++++ client/scripts/tnp3.lua | 78 ++++++++++++++++++++++++++++++++++------ common/crc16.c | 23 ++++++++++++ common/crc16.h | 5 +-- 5 files changed, 114 insertions(+), 13 deletions(-) diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index bff89c5f..15b96ee5 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -86,6 +86,15 @@ local Utils = end return t end, + ConvertHexToAscii = function(s) + local t={} + if s == nil then return t end + if #s == 0 then return t end + for k in s:gmatch"(%x%x)" do + table.insert(t, string.char(tonumber(k,16))) + end + return table.concat(t) + end, -- function convertStringToBytes(str) -- local bytes = {} diff --git a/client/scripting.c b/client/scripting.c index fd065a04..f0c56baf 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -19,6 +19,7 @@ #include "nonce2key/nonce2key.h" #include "../common/iso15693tools.h" #include +#include "../common/crc16.h" /** * The following params expected: * UsbCommand c @@ -263,6 +264,16 @@ static int l_aes(lua_State *L) return 1;// return 1 to signal one return value } +static int l_crc16(lua_State *L) +{ + size_t size; + const char *p_str = luaL_checklstring(L, 1, &size); + + unsigned short retval = crc16_ccitt( p_str, size); + lua_pushinteger(L, (int) retval); + return 1; +} + /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be * able to do "require('foobar')" if foobar.lua is within lualibs folder. @@ -301,6 +312,7 @@ int set_pm3_libraries(lua_State *L) {"console", l_CmdConsole}, {"iso15693_crc", l_iso15693_crc}, {"aes", l_aes}, + {"crc16", l_crc16}, {NULL, NULL} }; diff --git a/client/scripts/tnp3.lua b/client/scripts/tnp3.lua index 44e3753b..006e5a5d 100644 --- a/client/scripts/tnp3.lua +++ b/client/scripts/tnp3.lua @@ -93,6 +93,16 @@ local function waitCmd() return nil, "No response from device" end +local function computeCrc16(s) + local hash = core.crc16(utils.ConvertHexToAscii(s)) + return hash +end + +local function reverseCrcBytes(crc) + crc2 = crc:sub(3,4)..crc:sub(1,2) + return tonumber(crc2,16) +end + local function main(args) print( string.rep('--',20) ) @@ -104,7 +114,7 @@ local function main(args) local useNested = false local cmdReadBlockString = 'hf mf rdbl %d A %s' local input = "dumpkeys.bin" - local outputTemplate = os.date("toydump-%Y-%m-%d_%H%M%S"); + local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); -- Arguments for the script for o, a in getopt.getopt(args, 'hk:no:') do @@ -175,6 +185,7 @@ local function main(args) core.clearCommandBuffer() -- main loop + io.write('Decrypting blocks > ') for blockNo = 0, numBlocks-1, 1 do if core.ukbhit() then @@ -195,9 +206,8 @@ local function main(args) -- Block 0-7 not encrypted blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else - local base = ('%s%s%02d%s'):format(block0, block1, blockNo, hashconstant) - local baseArr = utils.ConvertHexStringToBytes(base) - local baseStr = utils.ConvertBytesToAsciiString(baseArr) + local base = ('%s%s%02x%s'):format(block0, block1, blockNo, hashconstant) + local baseStr = utils.ConvertHexToAscii(base) local md5hash = md5.sumhexa(baseStr) local aestest = core.aes(md5hash, blockdata) @@ -205,10 +215,12 @@ local function main(args) hex = utils.ConvertBytes2HexString(hex) --local _,hex = bin.unpack(("H%d"):format(16),aestest) + -- blocks with zero not encrypted. if string.find(blockdata, '^0+$') then blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + io.write( blockNo..',') end end else @@ -216,6 +228,7 @@ local function main(args) blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) end end + io.write('\n') core.clearCommandBuffer() @@ -224,7 +237,7 @@ local function main(args) local emldata = '' for _,s in pairs(blocks) do - local slice = s:sub(7,#s) + local slice = s:sub(8,#s) local str = utils.ConvertBytesToAsciiString( utils.ConvertHexStringToBytes(slice) ) @@ -235,10 +248,12 @@ local function main(args) end -- Write dump to files - local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin') - print(("Wrote a BIN dump to the file %s"):format(foo)) - local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml') - print(("Wrote a EML dump to the file %s"):format(bar)) + if not DEBUG then + local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin') + print(("Wrote a BIN dump to the file %s"):format(foo)) + local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml') + print(("Wrote a EML dump to the file %s"):format(bar)) + end local uid = block0:sub(1,8) local itemtype = block1:sub(1,4) @@ -251,6 +266,47 @@ local function main(args) print( (' CARDID : 0x%s'):format(cardid ) ) print( string.rep('--',20) ) -end + print('Validating checksums') + -- Checksum Typ 0 + local test1 = ('%s%s'):format(block0, block1:sub(1,28)) + local crc = block1:sub(29,32) + local revcrc = reverseCrcBytes(crc) + io.write( ('BLOCK 0-1 : %04x = %04x \n'):format(revcrc,computeCrc16(test1))) + + -- Checksum Typ 1 BLOCK 9 + local block9 = blocks[9]:sub(8,35) + test1 = ('%s0500'):format(block9) + crc = blocks[9]:sub(36,39) + revcrc = reverseCrcBytes(crc) + io.write( ('BLOCK 8 : %04x = %04x \n'):format(revcrc,computeCrc16(test1))) + + -- Checksum Typ 1 BLOCK 37 + local block37 = blocks[37]:sub(8,35) + test1 = ('%s0500'):format(block37) + crc = blocks[37]:sub(36,39) + revcrc = reverseCrcBytes(crc) + io.write( ('BLOCK 36 : %04x = %04x \n'):format(revcrc,computeCrc16(test1))) + + -- Checksum Typ 2 + -- 10,11,13 + test1 = blocks[10]:sub(8,39).. + blocks[11]:sub(8,39).. + blocks[13]:sub(8,39) + + crc = blocks[9]:sub(32,35) + revcrc = reverseCrcBytes(crc) + io.write( ('BLOCK 10-11-13 :%04x = %04x \n'):format(revcrc,computeCrc16(test1))) + -- Checksum Typ 3 + -- 15,17,18,19 + crc = blocks[9]:sub(28,31) + revcrc = reverseCrcBytes(crc) + test1 = blocks[14]:sub(8,39).. + blocks[15]:sub(8,39).. + blocks[17]:sub(8,39) + + local tohash = test1..string.rep('00',0xe0) + local hashed = computeCrc16(tohash) + io.write( ('BLOCK 14-15-17 %04x = %04x \n'):format(revcrc,hashed)) +end main(args) \ No newline at end of file diff --git a/common/crc16.c b/common/crc16.c index d181bb2a..973cd103 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -8,6 +8,7 @@ #include "crc16.h" + unsigned short update_crc16( unsigned short crc, unsigned char c ) { unsigned short i, v, tcrc = 0; @@ -20,3 +21,25 @@ unsigned short update_crc16( unsigned short crc, unsigned char c ) return ((crc >> 8) ^ tcrc)&0xffff; } + +uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial) { + + if (length == 0) + return (~remainder); + + for (int byte = 0; byte < length; ++byte) { + remainder ^= (message[byte] << 8); + for (uint8_t bit = 8; bit > 0; --bit) { + if (remainder & 0x8000) { + remainder = (remainder << 1) ^ polynomial; + } else { + remainder = (remainder << 1); + } + } + } + return remainder; +} + +uint16_t crc16_ccitt(uint8_t const *message, int length) { + return crc16(message, length, 0xffff, 0x1021); +} diff --git a/common/crc16.h b/common/crc16.h index 055a60bc..d16d83b5 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -5,10 +5,11 @@ //----------------------------------------------------------------------------- // CRC16 //----------------------------------------------------------------------------- +#include #ifndef __CRC16_H #define __CRC16_H - unsigned short update_crc16(unsigned short crc, unsigned char c); - +uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial); +uint16_t crc16_ccitt(uint8_t const *message, int length); #endif -- 2.39.2