From 9d512d411c8a86104f3d0c55bc0fbcacb57322ce Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 28 Apr 2019 23:43:55 +0200 Subject: [PATCH] chg: added manufacturer to 14ainfo structure. chg: ndefdump remakes --- client/lualibs/read14a.lua | 21 +++-- client/scripts/ndef_dump.lua | 159 +++++++++++++++-------------------- client/scripts/ufodump.lua | 21 +---- 3 files changed, 82 insertions(+), 119 deletions(-) diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 2f75fe81c..dfa2ea73c 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -11,6 +11,7 @@ --]] -- Loads the commands-library +local taglib = require('taglib') local cmds = require('commands') local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local ISO14A_COMMAND = { @@ -43,16 +44,12 @@ ISO14443a_TYPES[0x38] = "Nokia 6212 or 6131 MIFARE CLASSIC 4K" ISO14443a_TYPES[0x88] = "Infineon MIFARE CLASSIC 1K" ISO14443a_TYPES[0x98] = "Gemplus MPCOS" - local function tostring_14443a(sak) return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak) end local function parse14443a(data) --[[ - - Based on this struct : - typedef struct { uint8_t uid[10]; uint8_t uidlen; @@ -61,14 +58,20 @@ local function parse14443a(data) uint8_t ats_len; uint8_t ats[256]; } __attribute__((__packed__)) iso14a_card_select_t; - --]] local count, uid, uidlen, atqa, sak, ats_len, ats = bin.unpack('H10CH2CC',data) - uid = uid:sub(1, 2*uidlen) - --print("uid, atqa, sak: ",uid, atqa, sak) - --print("TYPE: ", tostring_1443a(sak)) - return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak), data = data} + uid = uid:sub(1, 2 * uidlen) + local man_byte = tonumber(uid:sub(1,2), 16) + + return { + uid = uid, + atqa = atqa, + sak = sak, + name = tostring_14443a(sak), + data = data, + manufacturer = taglib.lookupManufacturer(man_byte) + } end -- This function does a connect and retrieves som einfo diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index fee7af9fe..d184ee2d1 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -1,6 +1,6 @@ local getopt = require('getopt') local cmds = require('commands') -local taglib = require('taglib') +local lib14a = require('read14a') local utils = require('utils') copyright = '' @@ -64,93 +64,58 @@ local function help() print(example) print(usage) end - ---- This function is a lua-implementation of --- cmdhf14a.c:waitCmd(uint8_t iSelect) -local function waitCmd(iSelect) - local response = core.WaitForResponseTimeout(cmds.CMD_ACK, 1000) - if response then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) - - local iLen = arg0 - if iSelect then iLen = arg1 end - dbg(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) - if iLen == 0 then return nil, "No response from tag" end - local recv = string.sub(response,count, iLen+count-1) - return recv - end - return nil, "No response from device" +-- +-- Sends an instruction to do nothing, only disconnect +function disconnect() + local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,} + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return command:sendMIX(true) end --- -- -local function show(data) - local formatString = ('H%d'):format(string.len(data)) - local _,hexdata = bin.unpack(formatString, data) - dbg('Hexdata', hexdata) -end ---- Fire up a connection with a tag, return uid --- @return UID if successfull --- @return nil, errormessage if unsuccessfull -local function open() - dbg('Opening connection') - core.clearCommandBuffer() - local x = string.format('hf 14a raw -r -p -s') - dbg(x) - core.console(x) - dbg('done') - data, err = waitCmd(true) - if err then return oops(err) end - show(data) - local formatString = ('H%d'):format(string.len(data)) - local _,uid = bin.unpack(formatString, data) - return uid -end ---- Shut down tag communication --- return no return values -local function close() - dbg('Closing connection') - core.clearCommandBuffer() - local x = string.format('hf 14a raw -r') - dbg(x) - core.console(x) - dbg('done') +local function getblockdata(response) + if not response then + return nil, 'No response from device' + end + + local count, cmd, arg0 = bin.unpack('LL', response) + if arg0 == 1 then + local count, arg1, arg2, data = bin.unpack('LLH511', response, count) + return data:sub(1, 32) + else + return nil, "Couldn't read block" + end end ---_ Gets data from a block -- @return {block, block+1, block+2, block+3} if successfull -- @return nil, errormessage if unsuccessfull -local function getBlock(block) - local data, err - - core.clearCommandBuffer() - - local x = string.format('hf 14a raw -r -c -p 30 %02x', block) - dbg(x) - core.console(x) - dbg('done') - -- By now, there should be an ACK waiting from the device, since - -- we used the -r flag (don't read response). - - data, err = waitCmd(false) - if err then return oops(err) end - show(data) - - if string.len(data) < 18 then - return nil, ('Expected at least 18 bytes, got %d - this tag is not NDEF-compliant'):format(string.len(data)) +local function getBlock(blockno) + local block, err + local cmd = Command:newMIX{cmd = cmds.CMD_MIFAREU_READBL, arg1 = blockno, data = 0} + block, err = getblockdata(cmd:sendMIX(false)) + if not block then return oops(err) end + + if #block < 32 then + return nil, ('Expected at least 16 bytes, got %d - this tag is not NDEF-compliant'):format(string.len(data)) end + print('block', block) -- Now, parse out the block data -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC - b0 = string.sub(data, 1, 4) - b1 = string.sub(data, 5, 8) - b2 = string.sub(data, 9, 12) - b3 = string.sub(data, 13, 16) + b0 = string.sub(block, 1, 8) + b1 = string.sub(block, 9, 16) + b2 = string.sub(block, 17, 24) + b3 = string.sub(block, 25, 32) return {b0, b1, b2, b3} -end - +end +--- +-- local function main( args) print( string.rep('--',20) ) print( string.rep('--',20) ) + dbg('script started') local err, data, data2, k, v, i -- Read the parameters @@ -159,6 +124,21 @@ local function main( args) if o == 'd' then DEBUG = true end end + -- First of all, connect + info, err = lib14a.read(true, true) + if err then + disconnect(); + return oops(err) + end + core.clearCommandBuffer() + + if info.name:match("Ultralight") then + dbg('Found a tag') + else + disconnect() + return oops('Not a Ultralightbased card. This script reads NDEF formatted UL/NTAGS') + end + -- Info contained within the tag (block 0 example) -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC @@ -167,31 +147,24 @@ local function main( args) -- N = NDEF-Structure-Compliant (if value is E1) -- V = NFC Forum Specification version (if 10 = v1.0) - -- First, 'connect' (fire up the field) and get the uid - local uidHexstr = open() - -- First, get blockt 3 byte 2 local blocks, err = getBlock(0) if err then - close() + disconnect() return oops(err) end -- Block 3 contains number of blocks - local b3chars = {string.byte(blocks[4], 1,4)} + local b3chars = utils.ConvertHexToBytes(blocks[4]); local numBlocks = b3chars[3] * 2 + 6 print("Number of blocks:", numBlocks) -- NDEF compliant? if b3chars[1] ~= 0xE1 then - close() + disconnect() return oops('This tag is not NDEF-Compliant') end - local ndefVersion = b3chars[2] - - -- Block 1, byte 1 contains manufacturer info - local bl1_b1 = string.byte(blocks[1], 1) - local manufacturer = taglib.lookupManufacturer(bl1_b1) + local ndefversion = b3chars[2] -- Reuse existing info local blockData = {blocks[1], blocks[2], blocks[3], blocks[4]} @@ -202,22 +175,28 @@ local function main( args) removing bytes from 5 to 18 from each answer. --]] print('Dumping data...please wait') - for i=4,numBlocks-1,1 do + for i = 4, numBlocks - 1, 1 do blocks, err = getBlock(i) - if err then close(); return oops(err) end + if err then + disconnect(); + return oops(err) + end table.insert(blockData, blocks[1]) end -- Deactivate field - close() + disconnect() -- Print results - print(string.format('Tag manufacturer: %s', manufacturer)) - print(string.format('Tag UID: %s', uidHexstr)) - print(string.format('Tag NDEF version: 0x%02x', ndefVersion)) + print('Tag info') + print('UID ', info.uid) + print('NDEF version', ('%02x'):format(ndefversion)) + print('Manufacturer', info.manufacturer) + print('Type ', info.name) for k,v in ipairs(blockData) do print(string.format('Block %02x: %02x %02x %02x %02x', k-1, string.byte(v, 1,4))) end - local filename, err = utils.writeDumpFile(uidHexstr, blockData) + + local filename, err = utils.WriteDumpFile(info.uid, blockData) if err then return oops(err) end print(string.format('Dumped data into %s', filename)) diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua index 0270bafaa..d21e00497 100644 --- a/client/scripts/ufodump.lua +++ b/client/scripts/ufodump.lua @@ -62,25 +62,6 @@ local function help() print(usage) end -- --- writes data to ascii textfile. -function writeDumpFile(uid, blockData) - local destination = string.format('%s.eml', uid) - local file = io.open(destination, 'w') - if file == nil then - return nil, string.format('Could not write to file %s', destination) - end - local rowlen = string.len(blockData[1]) - - for i,block in ipairs(blockData) do - if rowlen ~= string.len(block) then - print(string.format('WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1',i)) - end - file:write(block..'\n') - end - file:close() - return destination -end --- --- Picks out and displays the data read from a tag -- Specifically, takes a usb packet, converts to a Command -- (as in commands.lua), takes the data-array and @@ -174,7 +155,7 @@ function main(args) print("----+------------------+-------------------") disconnect() - local filename, err = writeDumpFile(info.uid, blockData) + local filename, err = utils.WriteDumpFile(info.uid, blockData) if err then return oops(err) end print(string.format('\nDumped data into %s', filename))