From 47cbb2d41851e680c84b3a7dd0465f7f7960a9ec Mon Sep 17 00:00:00 2001
From: iceman1001 <iceman@iuse.se>
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 <openssl/aes.h>   
+#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 <stdint.h>
 
 #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.5