From: martin.holst@gmail.com <martin.holst@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Wed, 30 Oct 2013 21:10:47 +0000 (+0000)
Subject: First steps towards creating a generic HF reader/identifier. A coop with Asper.
X-Git-Tag: v1.0.0~28
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/5198f2e23c4d5c7fa9da7435c23f7a23457e5f2e?ds=sidebyside

First steps towards creating a generic HF reader/identifier. A coop with Asper.
---

diff --git a/client/lualibs/hf_reader.lua b/client/lualibs/hf_reader.lua
new file mode 100644
index 00000000..dc210688
--- /dev/null
+++ b/client/lualibs/hf_reader.lua
@@ -0,0 +1,186 @@
+[[
+THIS IS WORK IN PROGREESS, very much not finished. 
+
+This library utilises other libraries under the hood, but can be used as a generic reader for 13.56MHz tags. 
+]]
+
+local reader14443A = require('read14a')
+
+local function sendToDevice(command, ignoreresponse)
+	core.clearCommandBuffer()
+	local err = core.SendCommand(command:getBytes())
+	if err then
+		print(err)
+		return nil, err
+	end
+	if ignoreresponse then return nil,nil end
+
+	local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
+	return response,nil
+end
+
+-------------------------------------------------------
+-- This will be moved to a separate 14443B library
+-------------------------------------------------------
+
+local function read14443B()
+	return nil, "Not implemented"
+end
+local reader14443B = {
+	read = read14443B
+}	
+
+
+-------------------------------------------------------
+-- This will be moved to a separate 1593 library
+-------------------------------------------------------
+
+local function errorString15693(number)
+	local errors = {
+		0x01 :  "The command is not supported",
+		0x02 :  "The command is not recognised",
+		0x03 :  "The option is not supported.",
+		0x0f :  "Unknown error.",
+		0x10 :  "The specified block is not available (doesn’t exist).",
+		0x11 :  "The specified block is already -locked and thus cannot be locked again",
+		0x12 :  "The specified block is locked and its content cannot be changed.",
+		0x13 :  "The specified block was not successfully programmed.",
+		0x14 :  "The specified block was not successfully locked.",
+	}
+	return errors[number] or "Reserved for Future Use or Custom command error." 
+end
+-------------------------------------------------------
+-- This will be moved to a separate 1593 library
+-------------------------------------------------------
+
+local function parse15693(data)
+	-- From common/iso15693tools.h : 
+	--[[ 
+	#define ISO15_CRC_CHECK	 ((uint16_t)(~0xF0B8 & 0xFFFF)) 	// use this for checking of a correct crc
+	--]]
+	-- But that is very strange. Basically what is says is:
+	-- define ISO15_CRC_CHECK 0F47
+	-- So we can just use that directly... 
+	-- The following code is based on cmdhf15.c around line 666 (NoTB!) and onwards
+	if core.iso15693_crc(data, string.len(data)) ~= 0xF47 then
+		return nil, "CRC failed"
+	else if data[1] % 2 == 1 then
+		-- Above is a poor-mans bit check:
+		-- recv[0] & ISO15_RES_ERROR //(0x01)
+		local err = "Tag returned error %i: %s"
+		err = string.format(err, data[1],errorString15693(data[1]))
+		return nil, err
+	end
+	-- Finally, let the parsing begin... 
+	-- the UID is just the data in reverse... almost:
+	-- 	0FC481FF70000104E001001B0301
+	--	   8877665544332211
+	--  UID = E004010070FF81C4
+	--        1122334455667788
+	-- So, cut out the relevant part and reverse it
+	local uid = data:sub(2,9):reverse()
+	local uidStr = bin.unpack("H8", uid)
+
+	local _,manufacturer_code = bin.unpack("s",uid:sub(2,2))
+	local _,tag_size = bin.unpack(">I",data:sub(12,13))
+	local _,micref_modelcode = bin.unpack("s",data:sub(14,14))
+
+	return {
+		uid = uidStr,
+		manufacturer_code = manufacturer_code,
+		tag_size = tag_size,
+		micref_modelcode = micref_modelcode,
+	}
+end
+-------------------------------------------------------
+-- This will be moved to a separate 1593 library
+-------------------------------------------------------
+
+local function read15693()
+	[[
+
+	We start by trying this command:
+	 
+		proxmark3> hf 15 cmd sysinfo -2 u
+		0F C4 81 FF 70 00 01 04 E0 01 00 1B 03 01
+		UID = E004010070FF81C4
+		Philips; IC SL2 ICS20
+		DSFID supported, set to 01
+		AFI supported, set to 000
+		Tag provides info on memory layout (vendor dependent)
+		 4 (or 3) bytes/page x 28 pages
+		IC reference given: 01
+	 
+	This command is not always present in ISO15693 tags (it is an optional standard command) but if it is present usually the tags contain all the "colored" info above.
+	 
+	If the above command doesn't give an answer (see example below):
+	 
+		proxmark3> hf 15 cmd sysinfo -2 u
+		timeout: no
+		 
+	we must send the MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one):
+	 
+		proxmark3> hf 15 cmd inquiry
+		UID=E007C1A257394244         
+		Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit         
+		proxmark3>
+	 
+	From which we obtain less information than the above one.
+	]]
+
+	local command, result, info, err, data
+	local data = "02"
+	local datalen = string.len(data) / 2
+	local speed = 1
+	local recv = 1
+	command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, 
+								arg1 = datalen,arg2 = speed,arg3 =recv, data=data}
+	-- These are defined in common/iso15693tools.h
+
+	-- #define ISO15_REQ_SUBCARRIER_SINGLE	0x00	// Tag should respond using one subcarrier (ASK)
+	-- #define ISO15_REQ_DATARATE_HIGH		0x02	// Tag should respond using high data rate
+	-- #define ISO15_REQ_NONINVENTORY		0x00
+
+	local result,err = sendToDevice(command)
+
+	if not result then
+		print(err)
+		return nil, "15693 sysinfo: no answer"
+	end
+
+	local count,cmd,recvLen,arg1,arg2 = bin.unpack('LLLL',result)
+	data = string.sub(result,recvlen)
+	info, err = parse15693(data)
+	
+	if err then 
+		return nil, err
+	end
+
+	return info
+end
+
+
+}
+local reader15693 = {
+	read = read15693
+}
+
+
+---
+-- This method library can be set waits or a 13.56 MHz tag, and when one is found, returns info about
+-- what tag it is. 
+-- 
+-- @return if successfull: an table containing card info
+-- @return if unsuccessfull : nil, error
+local function waitForTag()
+	print("Waiting for card... press any key to quit")
+	local readers = [reader14443A, reader14443B, readerISO15693]
+	local r
+	while not core.ukbhit() do
+		for _, r in ipairs(readers) do
+			res, err = r.read()
+			if res then return res end
+			-- err means that there was no response from card
+	end
+	return nil, "Aborted by user"
+end
\ No newline at end of file
diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua
index cc3ba2eb..24021a1d 100644
--- a/client/lualibs/read14a.lua
+++ b/client/lualibs/read14a.lua
@@ -134,6 +134,7 @@ end
 local library = {
 	
 	read1443a = read14443a,
+	read 	= read14443a,
 	waitFor14443a = waitFor14443a,
 	parse1443a = parse1443a,
 	sendToDevice = sendToDevice,