lua: more fix mix of spaces & tabs

This commit is contained in:
Philippe Teuwen 2019-03-09 10:40:45 +01:00
commit 2d1a077ae4
14 changed files with 1423 additions and 1423 deletions

View file

@ -1,78 +1,78 @@
--[[ --[[
local _errorcodes = { local _errorcodes = {
SW_NO_ERROR = 0x9000, SW_NO_ERROR = 0x9000,
SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining
SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged = SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged =
SW_WRONG_LENGTH = 0x6700, -- : Wrong length SW_WRONG_LENGTH = 0x6700, -- : Wrong length
SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2) SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2)
SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le) SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le)
SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported
SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported
SW_UNKNOWN = 0x6F00, -- : No precise diagnosis SW_UNKNOWN = 0x6F00, -- : No precise diagnosis
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel
SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging
SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected
SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported
SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied
SW_FILE_INVALID = 0x6983, -- : File invalid SW_FILE_INVALID = 0x6983, -- : File invalid
SW_DATA_INVALID = 0x6984, -- : Data invalid SW_DATA_INVALID = 0x6984, -- : Data invalid
SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied
SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF) SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF)
SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed
SW_WRONG_DATA = 0x6A80, -- : Wrong data SW_WRONG_DATA = 0x6A80, -- : Wrong data
SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported
SW_FILE_NOT_FOUND = 0x6A82, -- : File not found SW_FILE_NOT_FOUND = 0x6A82, -- : File not found
SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found
SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file
SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2) SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2)
} }
--]] --]]
local _errorcodes = { local _errorcodes = {
SW_NO_ERROR = '9000', SW_NO_ERROR = '9000',
SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining
SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged = SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged =
SW_WRONG_LENGTH = '6700', -- : Wrong length SW_WRONG_LENGTH = '6700', -- : Wrong length
SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2) SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2)
SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le) SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le)
SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported
SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported
SW_UNKNOWN = '6F00', -- : No precise diagnosis SW_UNKNOWN = '6F00', -- : No precise diagnosis
SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel
SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging
SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected
SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported
SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied
SW_FILE_INVALID = '6983', -- : File invalid SW_FILE_INVALID = '6983', -- : File invalid
SW_DATA_INVALID = '6984', -- : Data invalid SW_DATA_INVALID = '6984', -- : Data invalid
SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied
SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF) SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF)
SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed
SW_WRONG_DATA = '6A80', -- : Wrong data SW_WRONG_DATA = '6A80', -- : Wrong data
SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported
SW_FILE_NOT_FOUND = '6A82', -- : File not found SW_FILE_NOT_FOUND = '6A82', -- : File not found
SW_RECORD_NOT_FOUND = '6A83', -- : Record not found SW_RECORD_NOT_FOUND = '6A83', -- : Record not found
SW_FILE_FULL = '6A84', -- : Not enough memory space in the file SW_FILE_FULL = '6A84', -- : Not enough memory space in the file
SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2) SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2)
} }
local _reverse_lookup,k,v = {} local _reverse_lookup,k,v = {}
for k, v in pairs(_errorcodes) do for k, v in pairs(_errorcodes) do
_reverse_lookup[v] = k _reverse_lookup[v] = k
end end
_errorcodes.tostring = function(command) _errorcodes.tostring = function(command)
if(type(command) == 'string') then if(type(command) == 'string') then
return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command) return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command)
end end
if(type(command) == 'number') then if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command) return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command)
end end
return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) return ("Error, numeric or string argument expected, got : %s"):format(tostring(command))
end end
return _errorcodes return _errorcodes

View file

@ -1,73 +1,73 @@
--[[ --[[
Handle Proxmark USB Commands Handle Proxmark USB Commands
--]] --]]
local _commands = require('usb_cmd') local _commands = require('usb_cmd')
local _reverse_lookup,k,v = {} local _reverse_lookup,k,v = {}
for k, v in pairs(_commands) do for k, v in pairs(_commands) do
_reverse_lookup[v] = k _reverse_lookup[v] = k
end end
_commands.tostring = function(command) _commands.tostring = function(command)
if(type(command) == 'number') then if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end end
return ("Error, numeric argument expected, got : %s"):format(tostring(command)) return ("Error, numeric argument expected, got : %s"):format(tostring(command))
end end
Command = { Command = {
new = function(self, o) new = function(self, o)
local o = o or {} -- create object if user does not provide one local o = o or {} -- create object if user does not provide one
setmetatable(o, self) -- DIY inheritance a'la javascript setmetatable(o, self) -- DIY inheritance a'la javascript
self.__index = self self.__index = self
o.cmd = o.cmd or _commands.CMD_UNKNOWN o.cmd = o.cmd or _commands.CMD_UNKNOWN
o.arg1 = o.arg1 or 0 o.arg1 = o.arg1 or 0
o.arg2 = o.arg2 or 0 o.arg2 = o.arg2 or 0
o.arg3 = o.arg3 or 0 o.arg3 = o.arg3 or 0
local data = o.data or "0" local data = o.data or "0"
if(type(data) == 'string') then if(type(data) == 'string') then
-- We need to check if it is correct length, otherwise pad it -- We need to check if it is correct length, otherwise pad it
local len = string.len(data) local len = string.len(data)
if(len < 1024) then if(len < 1024) then
--Should be 1024 hex characters to represent 512 bytes of data --Should be 1024 hex characters to represent 512 bytes of data
data = data .. string.rep("0",1024 - len ) data = data .. string.rep("0",1024 - len )
end end
if(len > 1024) then if(len > 1024) then
-- OOps, a bit too much data here -- OOps, a bit too much data here
print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) ) print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) )
-- --
data = data:sub(1,1024) data = data:sub(1,1024)
end end
else else
print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data))) print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data)))
end end
o.data = data o.data = data
return o return o
end, end,
parse = function (packet) parse = function (packet)
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet) local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data} return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
end end
} }
function Command:__tostring() function Command:__tostring()
local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format( local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format(
_commands.tostring(self.cmd), _commands.tostring(self.cmd),
tostring(self.arg1), tostring(self.arg1),
tostring(self.arg2), tostring(self.arg2),
tostring(self.arg3), tostring(self.arg3),
tostring(self.data)) tostring(self.data))
return output return output
end end
function Command:getBytes() function Command:getBytes()
--If a hex-string has been used --If a hex-string has been used
local data = self.data local data = self.data
local cmd = self.cmd local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
end end
return _commands return _commands

View file

@ -185,25 +185,25 @@ local _names = {
{"404", "9401", "0030", "earth", "legendary","Bash"}, {"404", "9401", "0030", "earth", "legendary","Bash"},
{"416", "a001", "0030", "magic", "legendary", "Spyro"}, {"416", "a001", "0030", "magic", "legendary", "Spyro"},
--{"", "", "0030", "magic", "legendary", "Deja Vu"}, --{"", "", "0030", "magic", "legendary", "Deja Vu"},
{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"}, {"419", "a301", "0030", "tech", "legendary", "Trigger Happy"},
--{"", "", "0030", "tech", "legendary", "bouncer"}, --{"", "", "0030", "tech", "legendary", "bouncer"},
--{"", "", "0030", "tech", "legendary", "jawbreaker"}, --{"", "", "0030", "tech", "legendary", "jawbreaker"},
{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"}, {"430", "ae01", "0030", "undead", "legendary", "Chop Chop"},
--{"", "", "0030", "undead", "legendary", "grim creeper"}, --{"", "", "0030", "undead", "legendary", "grim creeper"},
--{"", "", "0030", "undead", "legendary", "night shift"}, --{"", "", "0030", "undead", "legendary", "night shift"},
--{"", "", "0030", "air", "legendary", "blades"}, --{"", "", "0030", "air", "legendary", "blades"},
--{"", "", "0030", "air", "legendary", "jet vac"}, --{"", "", "0030", "air", "legendary", "jet vac"},
--{"", "", "0030", "air", "legendary", "Free Ranger"}, --{"", "", "0030", "air", "legendary", "Free Ranger"},
--{"", "", "0030", "life", "legendary", "stealth elf"}, --{"", "", "0030", "life", "legendary", "stealth elf"},
--{"", "", "0030", "life", "legendary", "Bushwhack"}, --{"", "", "0030", "life", "legendary", "Bushwhack"},
--{"", "", "0030", "fire", "legendary", "ignitor"}, --{"", "", "0030", "fire", "legendary", "ignitor"},
--{"", "", "0030", "water", "legendary", "slam bam"}, --{"", "", "0030", "water", "legendary", "slam bam"},
--{"", "", "0030", "water", "legendary", "chill"}, --{"", "", "0030", "water", "legendary", "chill"},
--{"", "", "0030", "", "legendary", "zoo lou"},
--{"", "", "0030", "", "legendary", "zoo lou"},
{"450", "c201", "0030", "air", "trapmaster", "Gusto"}, {"450", "c201", "0030", "air", "trapmaster", "Gusto"},
--{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"}, --{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"},
{"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"}, {"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"},
@ -453,23 +453,23 @@ local _names = {
local function find( main, sub) local function find( main, sub)
main = main:lower() main = main:lower()
sub = sub:lower() sub = sub:lower()
for k, v in pairs(_names) do for k, v in pairs(_names) do
if ( v[2]:lower() == main and v[3]:lower() == sub) then if ( v[2]:lower() == main and v[3]:lower() == sub) then
return v return v
end end
end end
return nil return nil
end end
local function list() local function list()
print ("Type\tSub\tElement\tGame Name") print ("Type\tSub\tElement\tGame Name")
print (string.rep('=', 54)) print (string.rep('=', 54))
for k, v in pairs(_names) do for k, v in pairs(_names) do
print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] )) print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] ))
end end
end end
return { return {
Find = find, Find = find,
List = list, List = list,
} }

View file

@ -1,5 +1,5 @@
--[[ --[[
decimal, di edition, model name decimal, di edition, model name
--]] --]]
local _names = { local _names = {
{"1000001","1","Mr. Incredible"}, {"1000001","1","Mr. Incredible"},
@ -319,8 +319,8 @@ local _names = {
{"4000226","3","?? unknown ??"}, {"4000226","3","?? unknown ??"},
{"4000227","3","?? unknown ??"}, {"4000227","3","?? unknown ??"},
{"4000229","3","Quad Jumper"}, {"4000229","3","Quad Jumper"},
--[[ --[[
these below are Portals. Not to be used for tags. these below are Portals. Not to be used for tags.
--]] --]]
{"8032384","0","Infinity Base - 3DS"}, {"8032384","0","Infinity Base - 3DS"},
{"8032385","0","Infinity Base - Xbox"}, {"8032385","0","Infinity Base - Xbox"},
@ -332,21 +332,21 @@ local _names = {
local function find( main ) local function find( main )
main = main:lower() main = main:lower()
for k, v in pairs(_names) do for k, v in pairs(_names) do
if ( v[1]:lower() == main ) then if ( v[1]:lower() == main ) then
return v return v
end end
end end
return nil return nil
end end
local function list() local function list()
print ("Type\tEdition\t Model name") print ("Type\tEdition\t Model name")
print (string.rep('=', 54)) print (string.rep('=', 54))
for k, v in pairs(_names) do for k, v in pairs(_names) do
print(("%s\t%s\t%s"):format(v[1],v[2],v[3] )) print(("%s\t%s\t%s"):format(v[1],v[2],v[3] ))
end end
end end
return { return {
Find = find, Find = find,
List = list, List = list,
} }

View file

@ -7,19 +7,19 @@ https://github.com/attractivechaos/klib/blob/master/lua/klib.lua
--[[ --[[
The MIT License The MIT License
Copyright (c) 2011, Attractive Chaos <attractor@live.co.uk> Copyright (c) 2011, Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -56,8 +56,8 @@ local function getopt(args, ostr)
return function () return function ()
if place == 0 then -- update scanning pointer if place == 0 then -- update scanning pointer
place = 1 place = 1
if #args == 0 if #args == 0
or args[1]:sub(1, 1) ~= '-' then or args[1]:sub(1, 1) ~= '-' then
place = 0; return nil end place = 0; return nil end
if #args[1] >= 2 then if #args[1] >= 2 then
place = place + 1 place = place + 1
@ -96,12 +96,12 @@ local function getopt(args, ostr)
if ostr:sub(1, 1) == ':' then return ':' end if ostr:sub(1, 1) == ':' then return ':' end
return '?'; return '?';
else arg = args[1] end else arg = args[1] end
end end
table.remove(args, 1); table.remove(args, 1);
place = 0; place = 0;
end end
return optopt, arg; return optopt, arg;
end end
end end
return { getopt = getopt } return { getopt = getopt }

View file

@ -1,7 +1,7 @@
--[[ --[[
THIS IS WORK IN PROGREESS, very much not finished. 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. 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 reader14443A = require('read14a')
@ -10,26 +10,26 @@ local reader15693 = require('read15')
--- ---
-- This method library can be set waits or a 13.56 MHz tag, and when one is found, returns info about -- 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. -- what tag it is.
-- --
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function waitForTag() local function waitForTag()
print("Waiting for card... press any key to quit") print("Waiting for card... press any key to quit")
local readers = {reader14443A, reader14443B, reader15693} local readers = {reader14443A, reader14443B, reader15693}
local i = 0; local i = 0;
while not core.ukbhit() do while not core.ukbhit() do
i = (i % 3) +1 i = (i % 3) +1
r = readers[i] r = readers[i]
print("Reading with ",i) print("Reading with ",i)
res, err = r.read() res, err = r.read()
if res then return res end if res then return res end
print(err) print(err)
-- err means that there was no response from card -- err means that there was no response from card
end end
return nil, "Aborted by user" return nil, "Aborted by user"
end end
return { return {
waitForTag = waitForTag, waitForTag = waitForTag,
} }

View file

@ -2,154 +2,154 @@ bin = require('bin')
------------------------------- -------------------------------
-- Some utilities -- Some utilities
------------------------------- -------------------------------
--- ---
-- A debug printout-function -- A debug printout-function
local function dbg(args) local function dbg(args)
if type(args) == "table" then if type(args) == "table" then
local i = 1 local i = 1
while args[i] do while args[i] do
print("###", args[i]) print("###", args[i])
i = i+1 i = i+1
end end
else else
print("###", args) print("###", args)
end end
end end
--- ---
-- This is only meant to be used when errors occur -- This is only meant to be used when errors occur
local function oops(err) local function oops(err)
print("ERROR: ",err) print("ERROR: ",err)
return nil, err return nil, err
end end
local function save_HTML(javascript, filename) local function save_HTML(javascript, filename)
-- Read the HTML-skel file -- Read the HTML-skel file
local skel = require("htmlskel") local skel = require("htmlskel")
html = skel.getHTML(javascript); html = skel.getHTML(javascript);
-- Open the output file -- Open the output file
local outfile = io.open(filename, "w")
if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename)))
end
-- Write the data into it
outfile:write(html)
io.close(outfile)
-- Done local outfile = io.open(filename, "w")
return filename if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename)))
end
-- Write the data into it
outfile:write(html)
io.close(outfile)
-- Done
return filename
end end
local function save_TEXT(data,filename) local function save_TEXT(data,filename)
-- Open the output file -- Open the output file
local outfile = io.open(filename, "w") local outfile = io.open(filename, "w")
if outfile == nil then if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename))) return oops(string.format("Could not write to file %s",tostring(filename)))
end end
outfile:write(data) outfile:write(data)
io.close(outfile) io.close(outfile)
return filename return filename
end end
local function save_BIN(data, filename) local function save_BIN(data, filename)
-- Open the output file -- Open the output file
local outfile = io.open(filename, "wb") local outfile = io.open(filename, "wb")
if outfile == nil then if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename))) return oops(string.format("Could not write to file %s",tostring(filename)))
end end
-- Write the data into it -- Write the data into it
local i = 1 local i = 1
while data[i] do while data[i] do
outfile:write(data[i]) outfile:write(data[i])
i = i+1 i = i+1
end end
io.close(outfile) io.close(outfile)
return filename return filename
end end
local function convert_ascii_dump_to_JS(infile) local function convert_ascii_dump_to_JS(infile)
local t = infile:read("*all") local t = infile:read("*all")
local cleaned local cleaned
local output = "["; local output = "[";
for line in string.gmatch(t, "[^\n]+") do for line in string.gmatch(t, "[^\n]+") do
if string.byte(line,1) ~= string.byte("+",1) then if string.byte(line,1) ~= string.byte("+",1) then
cleaned = (line or ''):gsub('%s+','') cleaned = (line or ''):gsub('%s+','')
output = output .. "'"..cleaned.."',\n" output = output .. "'"..cleaned.."',\n"
end end
end end
output = output .. "]" output = output .. "]"
return output return output
end end
local function convert_binary_dump_to_JS(infile, blockLen) local function convert_binary_dump_to_JS(infile, blockLen)
local bindata = infile:read("*all") local bindata = infile:read("*all")
len = string.len(bindata) len = string.len(bindata)
if len % blockLen ~= 0 then if len % blockLen ~= 0 then
return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen)) return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen))
end end
local _,hex = bin.unpack(("H%d"):format(len),bindata) local _,hex = bin.unpack(("H%d"):format(len),bindata)
-- Now that we've converted binary data into hex, we doubled the size. -- Now that we've converted binary data into hex, we doubled the size.
-- One byte, like 0xDE is now -- One byte, like 0xDE is now
-- the characters 'D' and 'E' : one byte each. -- the characters 'D' and 'E' : one byte each.
-- Thus: -- Thus:
blockLen = blockLen * 2 blockLen = blockLen * 2
local js,i = "["; local js,i = "[";
for i = 1, string.len(hex),blockLen do for i = 1, string.len(hex),blockLen do
js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n" js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n"
end end
js = js .. "]" js = js .. "]"
return js return js
end end
local function convert_ascii_dump_to_BIN(infile) local function convert_ascii_dump_to_BIN(infile)
local t = infile:read("*all") local t = infile:read("*all")
local cleaned local cleaned
local output = {}; local output = {};
for line in string.gmatch(t, "[^\n]+") do for line in string.gmatch(t, "[^\n]+") do
if string.byte(line) ~= string.byte("+") then if string.byte(line) ~= string.byte("+") then
cleaned = (line or ''):gsub('%s+','') cleaned = (line or ''):gsub('%s+','')
for c in cleaned:gmatch('..') do for c in cleaned:gmatch('..') do
output[#output+1] = string.char( tonumber(c,16) ) output[#output+1] = string.char( tonumber(c,16) )
end end
end end
end end
return output return output
end end
--- ---
-- Converts a .eml-file into a HTML/Javascript file. -- Converts a .eml-file into a HTML/Javascript file.
-- @param input the file to convert -- @param input the file to convert
-- @param output the file to write to -- @param output the file to write to
-- @return the name of the new file. -- @return the name of the new file.
local function convert_eml_to_html(input, output) local function convert_eml_to_html(input, output)
input = input or 'dumpdata.eml' input = input or 'dumpdata.eml'
output = output or input .. 'html' output = output or input .. 'html'
local infile = io.open(input, "r") local infile = io.open(input, "r")
if infile == nil then if infile == nil then
return oops(string.format("Could not read file %s",tostring(input))) return oops(string.format("Could not read file %s",tostring(input)))
end end
-- Read file, get JS -- Read file, get JS
local javascript = convert_ascii_dump_to_JS(infile) local javascript = convert_ascii_dump_to_JS(infile)
io.close(infile) io.close(infile)
return save_HTML(javascript, output ) return save_HTML(javascript, output )
end end
--- Converts a binary dump into HTML/Javascript file --- Converts a binary dump into HTML/Javascript file
@ -157,46 +157,46 @@ end
-- @param output the file to write to -- @param output the file to write to
-- @param blockLen, the length of each block. Defaults to 16 bytes -- @param blockLen, the length of each block. Defaults to 16 bytes
local function convert_bin_to_html(input, output, blockLen) local function convert_bin_to_html(input, output, blockLen)
input = input or 'dumpdata.bin' input = input or 'dumpdata.bin'
blockLen = blockLen or 16 blockLen = blockLen or 16
output = output or input .. 'html' output = output or input .. 'html'
local infile = io.open(input, "rb") local infile = io.open(input, "rb")
if infile == nil then if infile == nil then
return oops(string.format("Could not read file %s",tostring(input))) return oops(string.format("Could not read file %s",tostring(input)))
end end
-- Read file, get JS -- Read file, get JS
local javascript = convert_binary_dump_to_JS(infile, blockLen) local javascript = convert_binary_dump_to_JS(infile, blockLen)
io.close(infile) io.close(infile)
return save_HTML(javascript, output ) return save_HTML(javascript, output )
end end
--- Converts a eml dump into a binary file --- Converts a eml dump into a binary file
-- @param input the file containing the eml-dump (defaults to dumpdata.eml) -- @param input the file containing the eml-dump (defaults to dumpdata.eml)
-- @param output the file to write to ( defaults to dumpdata.bin) -- @param output the file to write to ( defaults to dumpdata.bin)
local function convert_eml_to_bin(input, output) local function convert_eml_to_bin(input, output)
input = input or 'dumpdata.eml' input = input or 'dumpdata.eml'
output = output or 'dumpdata.bin' output = output or 'dumpdata.bin'
local infile = io.open(input, "rb") local infile = io.open(input, "rb")
if infile == nil then if infile == nil then
return oops(string.format("Could not read file %s",tostring(input))) return oops(string.format("Could not read file %s",tostring(input)))
end end
-- Read file, get BIN -- Read file, get BIN
local data = convert_ascii_dump_to_BIN(infile) local data = convert_ascii_dump_to_BIN(infile)
io.close(infile) io.close(infile)
return save_BIN(data, output ) return save_BIN(data, output )
end end
return { return {
convert_bin_to_html = convert_bin_to_html, convert_bin_to_html = convert_bin_to_html,
convert_eml_to_html = convert_eml_to_html, convert_eml_to_html = convert_eml_to_html,
convert_eml_to_bin = convert_eml_to_bin, convert_eml_to_bin = convert_eml_to_bin,
SaveAsBinary = save_BIN, SaveAsBinary = save_BIN,
SaveAsText = save_TEXT, SaveAsText = save_TEXT,
SaveAsBinary = save_BIN, SaveAsBinary = save_BIN,
SaveAsText = save_TEXT, SaveAsText = save_TEXT,
} }

View file

@ -2,360 +2,360 @@ local skel_1 = [[
<html> <html>
<head> <head>
<script> <script>
var dictionary = {} var dictionary = {}
function add(commaSeparated) function add(commaSeparated)
{ {
var fields = commaSeparated.split(","); var fields = commaSeparated.split(",");
var manufacturerCode = fields[0]; var manufacturerCode = fields[0];
var modelCode = fields[1]; var modelCode = fields[1];
var modelSubCode= fields[2]; var modelSubCode= fields[2];
var modelName = fields[3]; var modelName = fields[3];
var ATQA = fields[4]; var ATQA = fields[4];
var SAK = fields[5]; var SAK = fields[5];
//In the data below, wrong endian is used. Mifare is //In the data below, wrong endian is used. Mifare is
// written as "0004" instead of "0400", so we need to // written as "0004" instead of "0400", so we need to
// flip it // flip it
ATQA = ATQA.substr(2,4)+ATQA.substr(0,2) ATQA = ATQA.substr(2,4)+ATQA.substr(0,2)
var info = { var info = {
modelCode : modelCode, modelCode : modelCode,
modelSubCode : modelSubCode, modelSubCode : modelSubCode,
modelName : modelName, modelName : modelName,
ATQA : ATQA, ATQA : ATQA,
SAK : SAK SAK : SAK
} }
console.log("Adding "+modelName+" , "+SAK) console.log("Adding "+modelName+" , "+SAK)
dictionary[ATQA] = dictionary[ATQA] || []; dictionary[ATQA] = dictionary[ATQA] || [];
dictionary[ATQA].push(info) dictionary[ATQA].push(info)
} }
function lookup(atqa, sak) function lookup(atqa, sak)
{ {
if (!dictionary[atqa]) return "UNKNOWN"; if (!dictionary[atqa]) return "UNKNOWN";
var possibleMatches = []; var possibleMatches = [];
for(var i = 0 ; i < dictionary[atqa].length ; i++) for(var i = 0 ; i < dictionary[atqa].length ; i++)
{ {
var info = dictionary[atqa][i]; var info = dictionary[atqa][i];
console.log("Comparing "+sak+ " with "+ info.SAK); console.log("Comparing "+sak+ " with "+ info.SAK);
if(sak && info.SAK == sak)//exact match if(sak && info.SAK == sak)//exact match
{ {
return info.modelName; return info.modelName;
// possibleMatches.push(info.modelName); // possibleMatches.push(info.modelName);
}else //SAK unknown }else //SAK unknown
{ {
possibleMatches.push(info.modelName); possibleMatches.push(info.modelName);
} }
} }
if(possibleMatches.length > 0) if(possibleMatches.length > 0)
return possibleMatches.join(" or "); return possibleMatches.join(" or ");
return "UNKNOWN" return "UNKNOWN"
} }
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01"); add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
add("04,,,Mifare Mini,0004,09"); add("04,,,Mifare Mini,0004,09");
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08"); add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10"); add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");
add("04,,,Mifare Plus (4 byte UID) 4K SL2,0004,11"); add("04,,,Mifare Plus (4 byte UID) 4K SL2,0004,11");
add("04,,,Mifare Plus (4 byte UID) 4K SL1,0004,18"); add("04,,,Mifare Plus (4 byte UID) 4K SL1,0004,18");
add("04,,,Mifare Plus (4 byte UID) 2K/4K SL3,0004,20"); add("04,,,Mifare Plus (4 byte UID) 2K/4K SL3,0004,20");
add("04,,,Mifare Classic 4K,0002,18"); add("04,,,Mifare Classic 4K,0002,18");
add("xx,,,NDEF Tags,0044,00 "); add("xx,,,NDEF Tags,0044,00 ");
add("04,,,Mifare Ultralight/UltralightC,0044,04"); add("04,,,Mifare Ultralight/UltralightC,0044,04");
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0042,08"); add("04,,,Mifare Plus (7 byte UID) 2K SL1,0042,08");
add("04,,,Mifare Plus (7 byte UID) 2K SL1,0044,08"); add("04,,,Mifare Plus (7 byte UID) 2K SL1,0044,08");
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0042,18"); add("04,,,Mifare Plus (7 byte UID) 4K SL1,0042,18");
add("04,,,Mifare Plus (7 byte UID) 4K SL1,0044,18"); add("04,,,Mifare Plus (7 byte UID) 4K SL1,0044,18");
add("04,,,Mifare Plus (7 byte UID),0042,10"); add("04,,,Mifare Plus (7 byte UID),0042,10");
add("04,,,Mifare Plus (7 byte UID),0044,10"); add("04,,,Mifare Plus (7 byte UID),0044,10");
add("04,,,Mifare Plus (7 byte UID),0042,11"); add("04,,,Mifare Plus (7 byte UID),0042,11");
add("04,,,Mifare Plus (7 byte UID),0044,11"); add("04,,,Mifare Plus (7 byte UID),0044,11");
add("04,,,Mifare Plus (7 byte UID),0042,20"); add("04,,,Mifare Plus (7 byte UID),0042,20");
add("04,,,Mifare Plus (7 byte UID),0044,20"); add("04,,,Mifare Plus (7 byte UID),0044,20");
add("04,,,Mifare DesFire / DesFire EV1,0344,20067577810280"); add("04,,,Mifare DesFire / DesFire EV1,0344,20067577810280");
add("04,,,JCOP31,0304,283877B14A434F503331"); add("04,,,JCOP31,0304,283877B14A434F503331");
add("04,,,JCOP31 v2.4.1,0048,207877B1024A434F5076323431"); add("04,,,JCOP31 v2.4.1,0048,207877B1024A434F5076323431");
add("04,,,JCOP41 v2.2,0048,203833B14A434F503431563232"); add("04,,,JCOP41 v2.2,0048,203833B14A434F503431563232");
add("04,,,JCOP41 v2.3.1,0004,283833B14A434F50343156323331"); add("04,,,JCOP41 v2.3.1,0004,283833B14A434F50343156323331");
add("05,,,Mifare Classic 1K,0004,88"); add("05,,,Mifare Classic 1K,0004,88");
add("40,,,MPCOS,0002,98"); add("40,,,MPCOS,0002,98");
add("25,,,Topaz/Topaz512/Jewel,0C00,"); add("25,,,Topaz/Topaz512/Jewel,0C00,");
add("1D,,,FM1208SH01,0004,53"); add("1D,,,FM1208SH01,0004,53");
add("1D,,,FM1208,0008,20"); add("1D,,,FM1208,0008,20");
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6212,0002,38"); add("Nokia,,,Mifare Classic 4K emulated by Nokia 6212,0002,38");
add("Nokia,,,Mifare Classic 4K emulated by Nokia 6131,0008,38"); add("Nokia,,,Mifare Classic 4K emulated by Nokia 6131,0008,38");
add("04,,,Smart MX with Mifare 4K emulation,0002"); add("04,,,Smart MX with Mifare 4K emulation,0002");
add("04,,,Smart MX with Mifare 4K emulation,0102"); add("04,,,Smart MX with Mifare 4K emulation,0102");
add("04,,,Smart MX with Mifare 4K emulation,0202"); add("04,,,Smart MX with Mifare 4K emulation,0202");
add("04,,,Smart MX with Mifare 4K emulation,0302"); add("04,,,Smart MX with Mifare 4K emulation,0302");
add("04,,,Smart MX with Mifare 4K emulation,0402"); add("04,,,Smart MX with Mifare 4K emulation,0402");
add("04,,,Smart MX with Mifare 4K emulation,0502"); add("04,,,Smart MX with Mifare 4K emulation,0502");
add("04,,,Smart MX with Mifare 4K emulation,0602"); add("04,,,Smart MX with Mifare 4K emulation,0602");
add("04,,,Smart MX with Mifare 4K emulation,0702"); add("04,,,Smart MX with Mifare 4K emulation,0702");
add("04,,,Smart MX with Mifare 4K emulation,0802"); add("04,,,Smart MX with Mifare 4K emulation,0802");
add("04,,,Smart MX with Mifare 4K emulation,0902"); add("04,,,Smart MX with Mifare 4K emulation,0902");
add("04,,,Smart MX with Mifare 4K emulation,0A02"); add("04,,,Smart MX with Mifare 4K emulation,0A02");
add("04,,,Smart MX with Mifare 4K emulation,0B02"); add("04,,,Smart MX with Mifare 4K emulation,0B02");
add("04,,,Smart MX with Mifare 4K emulation,0C02"); add("04,,,Smart MX with Mifare 4K emulation,0C02");
add("04,,,Smart MX with Mifare 4K emulation,0D02"); add("04,,,Smart MX with Mifare 4K emulation,0D02");
add("04,,,Smart MX with Mifare 4K emulation,0E02"); add("04,,,Smart MX with Mifare 4K emulation,0E02");
add("04,,,Smart MX with Mifare 4K emulation,0F02"); add("04,,,Smart MX with Mifare 4K emulation,0F02");
add("04,,,Smart MX with Mifare 1K emulation,0004"); add("04,,,Smart MX with Mifare 1K emulation,0004");
add("04,,,Smart MX with Mifare 1K emulation,0104"); add("04,,,Smart MX with Mifare 1K emulation,0104");
add("04,,,Smart MX with Mifare 1K emulation,0204"); add("04,,,Smart MX with Mifare 1K emulation,0204");
add("04,,,Smart MX with Mifare 1K emulation,0304"); add("04,,,Smart MX with Mifare 1K emulation,0304");
add("04,,,Smart MX with Mifare 1K emulation,0404"); add("04,,,Smart MX with Mifare 1K emulation,0404");
add("04,,,Smart MX with Mifare 1K emulation,0504"); add("04,,,Smart MX with Mifare 1K emulation,0504");
add("04,,,Smart MX with Mifare 1K emulation,0604"); add("04,,,Smart MX with Mifare 1K emulation,0604");
add("04,,,Smart MX with Mifare 1K emulation,0704"); add("04,,,Smart MX with Mifare 1K emulation,0704");
add("04,,,Smart MX with Mifare 1K emulation,0804"); add("04,,,Smart MX with Mifare 1K emulation,0804");
add("04,,,Smart MX with Mifare 1K emulation,0904"); add("04,,,Smart MX with Mifare 1K emulation,0904");
add("04,,,Smart MX with Mifare 1K emulation,0A04"); add("04,,,Smart MX with Mifare 1K emulation,0A04");
add("04,,,Smart MX with Mifare 1K emulation,0B04"); add("04,,,Smart MX with Mifare 1K emulation,0B04");
add("04,,,Smart MX with Mifare 1K emulation,0C04"); add("04,,,Smart MX with Mifare 1K emulation,0C04");
add("04,,,Smart MX with Mifare 1K emulation,0D04"); add("04,,,Smart MX with Mifare 1K emulation,0D04");
add("04,,,Smart MX with Mifare 1K emulation,0E04"); add("04,,,Smart MX with Mifare 1K emulation,0E04");
add("04,,,Smart MX with Mifare 1K emulation,0F04"); add("04,,,Smart MX with Mifare 1K emulation,0F04");
add("04,,,Smart MX with 7 byte UID,0048"); add("04,,,Smart MX with 7 byte UID,0048");
add("04,,,Smart MX with 7 byte UID,0148"); add("04,,,Smart MX with 7 byte UID,0148");
add("04,,,Smart MX with 7 byte UID,0248"); add("04,,,Smart MX with 7 byte UID,0248");
add("04,,,Smart MX with 7 byte UID,0348"); add("04,,,Smart MX with 7 byte UID,0348");
add("04,,,Smart MX with 7 byte UID,0448"); add("04,,,Smart MX with 7 byte UID,0448");
add("04,,,Smart MX with 7 byte UID,0548"); add("04,,,Smart MX with 7 byte UID,0548");
add("04,,,Smart MX with 7 byte UID,0648"); add("04,,,Smart MX with 7 byte UID,0648");
add("04,,,Smart MX with 7 byte UID,0748"); add("04,,,Smart MX with 7 byte UID,0748");
add("04,,,Smart MX with 7 byte UID,0848"); add("04,,,Smart MX with 7 byte UID,0848");
add("04,,,Smart MX with 7 byte UID,0948"); add("04,,,Smart MX with 7 byte UID,0948");
add("04,,,Smart MX with 7 byte UID,0A48"); add("04,,,Smart MX with 7 byte UID,0A48");
add("04,,,Smart MX with 7 byte UID,0B48"); add("04,,,Smart MX with 7 byte UID,0B48");
add("04,,,Smart MX with 7 byte UID,0C48"); add("04,,,Smart MX with 7 byte UID,0C48");
add("04,,,Smart MX with 7 byte UID,0D48"); add("04,,,Smart MX with 7 byte UID,0D48");
add("04,,,Smart MX with 7 byte UID,0E48"); add("04,,,Smart MX with 7 byte UID,0E48");
add("04,,,Smart MX with 7 byte UID,0F48"); add("04,,,Smart MX with 7 byte UID,0F48");
</script> </script>
<style> <style>
* { * {
background-color: #2F3440; background-color: #2F3440;
background-color:#232323; background-color:#232323;
color : #F5E5C0; color : #F5E5C0;
xtext-transform: uppercase; xtext-transform: uppercase;
font-size: 1.05em; font-size: 1.05em;
font-family: monospace,Arial; font-family: monospace,Arial;
} }
table{ table{
float:left; float:left;
border: 1px solid white; border: 1px solid white;
} }
td { td {
empty-cells: show; empty-cells: show;
} }
td.blockzero, .turqoise{ td.blockzero, .turqoise{
color: rgb(140, 245, 193); color: rgb(140, 245, 193);
} }
td.key_a, .yellow{ td.key_a, .yellow{
color : #F8CA4D; color : #F8CA4D;
} }
td.key_b, .blue{ td.key_b, .blue{
color : #3F5666; color : #3F5666;
} }
td.accessconditions, .red{ td.accessconditions, .red{
color : #EA6045; color : #EA6045;
} }
td.sectorhdr{
border-top: 1px solid white;
}
</style>
<script>
/** Jquery for the poor **/
function dc(x){return document.createElement(x)}
function tr(table){ td.sectorhdr{
var row = dc('tr'); border-top: 1px solid white;
table.appendChild(row); }
return row; </style>
} <script>
function td(row, text){ /** Jquery for the poor **/
var tdata = dc('td'); function dc(x){return document.createElement(x)}
row.appendChild(tdata);
tdata.appendChild(document.createTextNode(text))
return tdata;
}
/** function tr(table){
* The identifiers that determine how to highlight data and present information var row = dc('tr');
**/ table.appendChild(row);
var identifiers = [ return row;
function(data) }
{ function td(row, text){
// Should be 32 characters long ( 16 bytes per block) var tdata = dc('td');
if(data[0].length != 32) { return false; } row.appendChild(tdata);
// ... add more checks if necessary ... tdata.appendChild(document.createTextNode(text))
return tdata;
}
var info = {Type : "Mifare"} /**
info['Size'] = (data[0].length / 2 * data.length) + " Bytes"; * The identifiers that determine how to highlight data and present information
info['UID'] = data[0].substring(0,8); **/
info['SAK'] = data[0].substring(10,12); var identifiers = [
info['ATQA'] = data[0].substring(12,16); function(data)
{
// Should be 32 characters long ( 16 bytes per block)
if(data[0].length != 32) { return false; }
// ... add more checks if necessary ...
info['Name'] = lookup(info.ATQA, info.SAK); var info = {Type : "Mifare"}
return {info: info, highlighter : mifareHighlighter } info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
}, info['UID'] = data[0].substring(0,8);
function(data) info['SAK'] = data[0].substring(10,12);
{ info['ATQA'] = data[0].substring(12,16);
// Should be 8 characters long ( 4 bytes per block)
if(data[0].length != 8) { return false; }
// ... add more checks if necessary ...
var info = {Type : "NDEF"}
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
return {info: info, highlighter : ndefHighligheter } info['Name'] = lookup(info.ATQA, info.SAK);
}, return {info: info, highlighter : mifareHighlighter }
},
function(data)
{
// Should be 8 characters long ( 4 bytes per block)
if(data[0].length != 8) { return false; }
// ... add more checks if necessary ...
var info = {Type : "NDEF"}
info['Size'] = (data[0].length / 2 * data.length) + " Bytes";
function(data) return {info: info, highlighter : ndefHighligheter }
{//This is the catch-all },
return {info: {type : "Unknown"}, highlighter : noHighlighter}
}
]
/** function(data)
* Helper function to convert bin-data into printable chars {//This is the catch-all
**/ return {info: {type : "Unknown"}, highlighter : noHighlighter}
}
function to_ascii(hexval) ]
{
var intval = parseInt(hexval,16);
if(intval > 31 && intval < 127)
{
return String.fromCharCode(intval);
}
return ".";
}
function loadIntoTable(data, info, ascii) /**
{ * Helper function to convert bin-data into printable chars
var t = dc("table") **/
for(var i = 0 ; i < data.length ; i++)
{
line = data[i];
var row = tr(t);
var bytes = line.match(/(.{1,2})/g);
for(var b = 0 ; b < bytes.length ; b++)
{
var elem = td(row, ascii ? to_ascii(bytes[b]) : bytes[b]);
info.highlighter.addClass(elem,i,b, bytes[b]);
}
}
document.body.appendChild(t);
}
function loadGeneralInfo(data, info)
{
var t = dc("table");
for (var key in info)
{
var row = tr(t);
td(row,key);
td(row,info[key]);
}
document.body.appendChild(t);
}
function handle(dump) function to_ascii(hexval)
{ {
var data = dump.data; var intval = parseInt(hexval,16);
var info = null; if(intval > 31 && intval < 127)
for(var i = 0; i < identifiers.length && !info; i++) {
info = identifiers[i](data); return String.fromCharCode(intval);
}
return ".";
}
console.log(info);
loadIntoTable(data, info, false); function loadIntoTable(data, info, ascii)
loadIntoTable(data, info, true); {
loadGeneralInfo(data, info.info); var t = dc("table")
for(var i = 0 ; i < data.length ; i++)
{
line = data[i];
var row = tr(t);
var bytes = line.match(/(.{1,2})/g);
for(var b = 0 ; b < bytes.length ; b++)
{
var elem = td(row, ascii ? to_ascii(bytes[b]) : bytes[b]);
info.highlighter.addClass(elem,i,b, bytes[b]);
}
}
document.body.appendChild(t);
}
function loadGeneralInfo(data, info)
{
var t = dc("table");
for (var key in info)
{
var row = tr(t);
td(row,key);
td(row,info[key]);
}
document.body.appendChild(t);
}
} function handle(dump)
var noHighlighter = { {
addClass : function(el ,line, byte) var data = dump.data;
{ var info = null;
return; for(var i = 0; i < identifiers.length && !info; i++)
} info = identifiers[i](data);
};
var ndefHighligheter = {
addClass : function(el ,line, byte, value)
{
if(line < 3)
{
el.className += " red";
}
if ( line == 3)
{
console.log(value);
if( byte == 0 && "e1" == value.toLowerCase()) el.className += " turqoise";
if( byte == 1 ) el.className += " yellow";
if( byte == 2 ) el.className += " blue";
return;
}
}
};
var mifareHighlighter = {
addClass : function(el ,line, byte)
{
if (line == 0)
{
el.className += " blockzero";
}
if(line < 128){
linesPerSector = 4;
} else {
//Quadruple size sectors
linesPerSector = 16;
line = line - 128;
}
if(line % linesPerSector == 0) console.log(info);
{
el.className += " sectorhdr";
}
if(line % linesPerSector == (linesPerSector -1))
{
el.className += " sectortrailer";
if(byte == undefined)
{
return;
}
if(byte < 6) el.className += " key_a"; loadIntoTable(data, info, false);
else if(byte < 10) el.className += " accessconditions"; loadIntoTable(data, info, true);
else el.className += " key_b"; loadGeneralInfo(data, info.info);
}
} }
}; var noHighlighter = {
addClass : function(el ,line, byte)
{
return;
}
};
var ndefHighligheter = {
addClass : function(el ,line, byte, value)
{
if(line < 3)
{
el.className += " red";
}
if ( line == 3)
{
console.log(value);
if( byte == 0 && "e1" == value.toLowerCase()) el.className += " turqoise";
if( byte == 1 ) el.className += " yellow";
if( byte == 2 ) el.className += " blue";
return;
}
}
};
var mifareHighlighter = {
addClass : function(el ,line, byte)
{
if (line == 0)
{
el.className += " blockzero";
}
if(line < 128){
linesPerSector = 4;
} else {
//Quadruple size sectors
linesPerSector = 16;
line = line - 128;
}
if(line % linesPerSector == 0)
{
el.className += " sectorhdr";
}
if(line % linesPerSector == (linesPerSector -1))
{
el.className += " sectortrailer";
if(byte == undefined)
{
return;
}
if(byte < 6) el.className += " key_a";
else if(byte < 10) el.className += " accessconditions";
else el.className += " key_b";
}
}
};
</script>
</script>
</head> </head>
<body></body> <body></body>
<script> <script>
var x = { data : var x = { data :
]] ]]
local skel_2 = [[ local skel_2 = [[
}; };
handle(x); handle(x);
</script> </script>
</html> </html>
]] ]]
local function getHTML(data) local function getHTML(data)
return skel_1 .. data .. skel_2 return skel_1 .. data .. skel_2
end end
return {getHTML = getHTML} return {getHTML = getHTML}

View file

@ -1,5 +1,5 @@
--[[ --[[
This is an experimental lib. This is an experimental lib.
--]] --]]
local utils = require('utils') local utils = require('utils')
@ -35,60 +35,60 @@ shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x
shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe } shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
local function ApplyPermutationAndShifts( pos, value, nibble) local function ApplyPermutationAndShifts( pos, value, nibble)
local shiftbytes = shifts[pos] local shiftbytes = shifts[pos]
local shiftElem = shiftbytes[nibble+1] --one indexed local shiftElem = shiftbytes[nibble+1] --one indexed
local shiftOne = shiftbytes[1] local shiftOne = shiftbytes[1]
local rs = bit32.bxor(value, shiftOne, shiftElem) local rs = bit32.bxor(value, shiftOne, shiftElem)
return rs return rs
end end
local function GetOne( uid, block ) local function GetOne( uid, block )
if uid == nil then return nil, 'empty uid string' end if uid == nil then return nil, 'empty uid string' end
if #uid == 0 then return nil, 'empty uid string' end if #uid == 0 then return nil, 'empty uid string' end
if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
if type(block) ~= 'number' then return nil, 'block is not number' end if type(block) ~= 'number' then return nil, 'block is not number' end
if block > 16 or block < 0 then return nil, 'block is out-of-range' end if block > 16 or block < 0 then return nil, 'block is out-of-range' end
local s = ('%s%02X'):format(uid,block)
local nibble1 = tonumber(s:sub(1,1),16) + 1
local permuted = '' local s = ('%s%02X'):format(uid,block)
for i = 1, #s do local nibble1 = tonumber(s:sub(1,1),16) + 1
local el_row = shifts[i]
local el_value = el_row[nibble1]
j = 1
while j <= i do
if i-j > 0 then
local nibble = tonumber(s:sub(j+1,j+1),16)
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
end
j = j+1
end
permuted =('%s%X'):format(permuted,el_value)
end
permuted = 'C2'..permuted local permuted = ''
local crc64numStr = utils.Crc64(permuted) for i = 1, #s do
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true) local el_row = shifts[i]
local key = utils.ConvertBytesToHex(keybytes) local el_value = el_row[nibble1]
return key:sub(1,12) j = 1
while j <= i do
if i-j > 0 then
local nibble = tonumber(s:sub(j+1,j+1),16)
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
end
j = j+1
end
permuted =('%s%X'):format(permuted,el_value)
end
permuted = 'C2'..permuted
local crc64numStr = utils.Crc64(permuted)
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
local key = utils.ConvertBytesToHex(keybytes)
return key:sub(1,12)
end end
local PreCalc = local PreCalc =
{ {
GetAll = function(id) GetAll = function(id)
if id == nil then return nil, 'empty string' end if id == nil then return nil, 'empty string' end
if #id == 0 then return nil, 'empty string' end if #id == 0 then return nil, 'empty string' end
if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
local list = '4b0b20107ccb' local list = '4b0b20107ccb'
for i = 1,15 do for i = 1,15 do
local key, err = GetOne(id,i) local key, err = GetOne(id,i)
if not key then return oops(err) end if not key then return oops(err) end
list = list..key list = list..key
end end
return list return list
end, end,
} }
return PreCalc return PreCalc

View file

@ -1,32 +1,32 @@
--[[ --[[
This is a library to read 14443a tags. It can be used something like this This is a library to read 14443a tags. It can be used something like this
local reader = require('read14a') local reader = require('read14a')
result, err = reader.read14443a() result, err = reader.read14443a()
if not result then if not result then
print(err) print(err)
return return
end end
print(result.name) print(result.name)
--]] --]]
-- Loads the commands-library -- Loads the commands-library
local cmds = require('commands') local cmds = require('commands')
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local ISO14A_COMMAND = { local ISO14A_COMMAND = {
ISO14A_CONNECT = 1, ISO14A_CONNECT = 1,
ISO14A_NO_DISCONNECT = 2, ISO14A_NO_DISCONNECT = 2,
ISO14A_APDU = 4, ISO14A_APDU = 4,
ISO14A_RAW = 8, ISO14A_RAW = 8,
ISO14A_REQUEST_TRIGGER = 0x10, ISO14A_REQUEST_TRIGGER = 0x10,
ISO14A_APPEND_CRC = 0x20, ISO14A_APPEND_CRC = 0x20,
ISO14A_SET_TIMEOUT = 0x40, ISO14A_SET_TIMEOUT = 0x40,
ISO14A_NO_SELECT = 0x80, ISO14A_NO_SELECT = 0x80,
ISO14A_TOPAZMODE = 0x100, ISO14A_TOPAZMODE = 0x100,
ISO14A_NO_RATS = 0x200 ISO14A_NO_RATS = 0x200
} }
local ISO14443a_TYPES = {} local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C | NTAG" ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C | NTAG"
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance" ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)" ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
@ -45,50 +45,50 @@ ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
local function tostring_14443a(sak) local function tostring_14443a(sak)
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak) return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
end end
local function parse14443a(data) local function parse14443a(data)
--[[ --[[
Based on this struct : Based on this struct :
typedef struct { typedef struct {
byte_t uid[10]; byte_t uid[10];
byte_t uidlen; byte_t uidlen;
byte_t atqa[2]; byte_t atqa[2];
byte_t sak; byte_t sak;
byte_t ats_len; byte_t ats_len;
byte_t ats[256]; byte_t ats[256];
} __attribute__((__packed__)) iso14a_card_select_t; } __attribute__((__packed__)) iso14a_card_select_t;
--]] --]]
local count, uid, uidlen, atqa, sak, ats_len, ats = bin.unpack('H10CH2CC',data) local count, uid, uidlen, atqa, sak, ats_len, ats = bin.unpack('H10CH2CC',data)
uid = uid:sub(1, 2*uidlen) uid = uid:sub(1, 2*uidlen)
--print("uid, atqa, sak: ",uid, atqa, sak) --print("uid, atqa, sak: ",uid, atqa, sak)
--print("TYPE: ", tostring_1443a(sak)) --print("TYPE: ", tostring_1443a(sak))
return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak), data = data} return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak), data = data}
end end
--- Sends a USBpacket to the device --- Sends a USBpacket to the device
-- @param command - the usb packet to send -- @param command - the usb packet to send
-- @param ignoreresponse - if set to true, we don't read the device answer packet -- @param ignoreresponse - if set to true, we don't read the device answer packet
-- which is usually recipe for fail. If not sent, the host will wait 2s for a -- which is usually recipe for fail. If not sent, the host will wait 2s for a
-- response of type CMD_ACK -- response of type CMD_ACK
-- @return packet,nil if successfull -- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull -- nil, errormessage if unsuccessfull
local function sendToDevice(command, ignoreresponse) local function sendToDevice(command, ignoreresponse)
--core.clearCommandBuffer() --core.clearCommandBuffer()
local err = core.SendCommand(command:getBytes()) local err = core.SendCommand(command:getBytes())
if err then if err then
print(err) print(err)
return nil, err return nil, err
end end
if ignoreresponse then return nil,nil end if ignoreresponse then return nil,nil end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
return response,nil return response,nil
end end
-- This function does a connect and retrieves som einfo -- This function does a connect and retrieves som einfo
@ -96,34 +96,34 @@ end
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function read14443a(dont_disconnect, no_rats) local function read14443a(dont_disconnect, no_rats)
local command, result, info, err, data local command, result, info, err, data
command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT } command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT }
if dont_disconnect then if dont_disconnect then
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT
end end
if no_rats then if no_rats then
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS
end end
local result,err = sendToDevice(command)
if result then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
if arg0 == 0 then
return nil, "iso14443a card select failed"
end
data = string.sub(result,count)
info, err = parse14443a(data)
else
err ="No response from card"
end
if err then local result,err = sendToDevice(command)
print(err) if result then
return nil, err local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
end if arg0 == 0 then
return info return nil, "iso14443a card select failed"
end
data = string.sub(result,count)
info, err = parse14443a(data)
else
err ="No response from card"
end
if err then
print(err)
return nil, err
end
return info
end end
--- ---
@ -131,20 +131,20 @@ end
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function waitFor14443a() local function waitFor14443a()
print("Waiting for card... press any key to quit") print("Waiting for card... press any key to quit")
while not core.ukbhit() do while not core.ukbhit() do
res, err = read14443a() res, err = read14443a()
if res then return res end if res then return res end
-- err means that there was no response from card -- err means that there was no response from card
end end
return nil, "Aborted by user" return nil, "Aborted by user"
end end
local library = { local library = {
read = read14443a, read = read14443a,
waitFor14443a = waitFor14443a, waitFor14443a = waitFor14443a,
parse14443a = parse14443a, parse14443a = parse14443a,
sendToDevice = sendToDevice, sendToDevice = sendToDevice,
ISO14A_COMMAND = ISO14A_COMMAND, ISO14A_COMMAND = ISO14A_COMMAND,
} }
return library return library

View file

@ -1,13 +1,13 @@
--[[ --[[
This is a library to read 14443b tags. It can be used something like this This is a library to read 14443b tags. It can be used something like this
local reader = require('read14b') local reader = require('read14b')
result, err = reader.select1443b() result, err = reader.select1443b()
if not result then if not result then
print(err) print(err)
return return
end end
print(result.name) print(result.name)
--]] --]]
-- Loads the commands-library -- Loads the commands-library
@ -15,68 +15,68 @@ local cmds = require('commands')
local utils = require('utils') local utils = require('utils')
local TIMEOUT = 2500 local TIMEOUT = 2500
local ISO14B_COMMAND = { local ISO14B_COMMAND = {
ISO14B_CONNECT = 1, ISO14B_CONNECT = 1,
ISO14B_DISCONNECT = 2, ISO14B_DISCONNECT = 2,
ISO14B_APDU = 4, ISO14B_APDU = 4,
ISO14B_RAW = 8, ISO14B_RAW = 8,
ISO14B_REQUEST_TRIGGER = 0x10, ISO14B_REQUEST_TRIGGER = 0x10,
ISO14B_APPEND_CRC = 0x20, ISO14B_APPEND_CRC = 0x20,
ISO14B_SELECT_STD = 0x40, ISO14B_SELECT_STD = 0x40,
ISO14B_SELECT_SR = 0x80, ISO14B_SELECT_SR = 0x80,
} }
local function parse1443b(data) local function parse1443b(data)
--[[ --[[
Based on this struct :
typedef struct {
byte_t uid[10];
byte_t uidlen;
byte_t atqb[7];
byte_t chipid;
byte_t cid;
} __attribute__((__packed__)) iso14b_card_select_t;
--]] Based on this struct :
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data) typedef struct {
uid = uid:sub(1, 2*uidlen) byte_t uid[10];
return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid } byte_t uidlen;
byte_t atqb[7];
byte_t chipid;
byte_t cid;
} __attribute__((__packed__)) iso14b_card_select_t;
--]]
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
uid = uid:sub(1, 2*uidlen)
return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid }
end end
--- Sends a USBpacket to the device --- Sends a USBpacket to the device
-- @param command - the usb packet to send -- @param command - the usb packet to send
-- @param ignoreresponse - if set to true, we don't read the device answer packet -- @param ignoreresponse - if set to true, we don't read the device answer packet
-- which is usually recipe for fail. If not sent, the host will wait 2s for a -- which is usually recipe for fail. If not sent, the host will wait 2s for a
-- response of type CMD_ACK -- response of type CMD_ACK
-- @return packet,nil if successfull -- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull -- nil, errormessage if unsuccessfull
local function sendToDevice(cmd, ignoreresponse) local function sendToDevice(cmd, ignoreresponse)
--core.clearCommandBuffer() --core.clearCommandBuffer()
local bytes = cmd:getBytes() local bytes = cmd:getBytes()
local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes) local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes)
local err = core.SendCommand(cmd:getBytes()) local err = core.SendCommand(cmd:getBytes())
if err then if err then
print('ERROR',err) print('ERROR',err)
return nil, err return nil, err
end end
if ignoreresponse then return nil,nil end if ignoreresponse then return nil,nil end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
return response,nil return response,nil
end end
--- Picks out and displays the data read from a tag --- Picks out and displays the data read from a tag
-- Specifically, takes a usb packet, converts to a Command -- Specifically, takes a usb packet, converts to a Command
-- (as in commands.lua), takes the data-array and -- (as in commands.lua), takes the data-array and
-- reads the number of bytes specified in arg1 (arg0 in c-struct) -- reads the number of bytes specified in arg1 (arg0 in c-struct)
-- and displays the data -- and displays the data
-- @param usbpacket the data received from the device -- @param usbpacket the data received from the device
local function showData(usbpacket) local function showData(usbpacket)
local response = Command.parse(usbpacket) local response = Command.parse(usbpacket)
local len = response.arg2 * 2 local len = response.arg2 * 2
local data = string.sub(response.data, 0, len); local data = string.sub(response.data, 0, len);
print("<< ",data) print("<< ",data)
end end
@ -85,74 +85,74 @@ end
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function read14443b(disconnect) local function read14443b(disconnect)
local command, result, info, err, data local command, result, info, err, data
local flags = ISO14B_COMMAND.ISO14B_CONNECT + local flags = ISO14B_COMMAND.ISO14B_CONNECT +
ISO14B_COMMAND.ISO14B_SELECT_STD ISO14B_COMMAND.ISO14B_SELECT_STD
if disconnect then
print('DISCONNECT')
flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
end
command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} if disconnect then
local result, err = sendToDevice(command, false) print('DISCONNECT')
if result then flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) end
if arg0 == 0 then
data = string.sub(result, count)
info, err = parse1443b(data)
else
err = "iso14443b card select failed"
end
else
err = "No response from card"
end
if err then command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
print(err) local result, err = sendToDevice(command, false)
return nil, err if result then
end local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
return info if arg0 == 0 then
data = string.sub(result, count)
info, err = parse1443b(data)
else
err = "iso14443b card select failed"
end
else
err = "No response from card"
end
if err then
print(err)
return nil, err
end
return info
end end
--PING / PONG - Custom Anticollison for Navigo. --PING / PONG - Custom Anticollison for Navigo.
-- AA / BB ?!? -- AA / BB ?!?
-- local ping = ('BA00') -- local ping = ('BA00')
-- result, err = sendRaw(ping, 1, 1) -- result, err = sendRaw(ping, 1, 1)
-- if result then -- if result then
-- resp = Command.parse( result ) -- resp = Command.parse( result )
-- if arg1 == 0 then -- if arg1 == 0 then
-- return nil, "iso14443b card - PING/PONG failed" -- return nil, "iso14443b card - PING/PONG failed"
-- end -- end
-- showData(result) -- showData(result)
-- else -- else
-- err = "No response from card" -- err = "No response from card"
-- print(err) -- print(err)
-- return nil, err -- return nil, err
-- end -- end
--- ---
-- Waits for a mifare card to be placed within the vicinity of the reader. -- Waits for a mifare card to be placed within the vicinity of the reader.
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function waitFor14443b() local function waitFor14443b()
print("Waiting for card... press any key to quit") print("Waiting for card... press any key to quit")
while not core.ukbhit() do while not core.ukbhit() do
res, err = read14443b(false) res, err = read14443b(false)
if res then return res end if res then return res end
-- err means that there was no response from card -- err means that there was no response from card
end end
return nil, "Aborted by user" return nil, "Aborted by user"
end end
local library = { local library = {
read = read14443b, read = read14443b,
waitFor14443b = waitFor14443b, waitFor14443b = waitFor14443b,
parse1443b = parse1443b, parse1443b = parse1443b,
sendToDevice = sendToDevice, sendToDevice = sendToDevice,
showData = showData, showData = showData,
ISO14B_COMMAND = ISO14B_COMMAND, ISO14B_COMMAND = ISO14B_COMMAND,
} }
return library return library

View file

@ -1,13 +1,13 @@
--[[ --[[
This is a library to read 15693 tags. It can be used something like this This is a library to read 15693 tags. It can be used something like this
local reader = require('read15') local reader = require('read15')
local info, err = reader.read() local info, err = reader.read()
if not info then if not info then
print(err) print(err)
return return
end end
print(info.UID) print(info.UID)
--]] --]]
-- Loads the commands-library -- Loads the commands-library
@ -19,60 +19,60 @@ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
--- Sends a USBpacket to the device --- Sends a USBpacket to the device
-- @param command - the usb packet to send -- @param command - the usb packet to send
-- @param ignoreresponse - if set to true, we don't read the device answer packet -- @param ignoreresponse - if set to true, we don't read the device answer packet
-- which is usually recipe for fail. If not sent, the host will wait 2s for a -- which is usually recipe for fail. If not sent, the host will wait 2s for a
-- response of type CMD_ACK -- response of type CMD_ACK
-- @return packet,nil if successfull -- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull -- nil, errormessage if unsuccessfull
local function sendToDevice(command, ignoreresponse) local function sendToDevice(command, ignoreresponse)
local err = core.SendCommand(command:getBytes()) local err = core.SendCommand(command:getBytes())
if err then if err then
print(err) print(err)
return nil, err return nil, err
end end
if ignoreresponse then return nil, nil end if ignoreresponse then return nil, nil end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
return response, nil return response, nil
end end
local function errorString15693(number) local function errorString15693(number)
local errors = {} local errors = {}
errors[0x01] = "The command is not supported" errors[0x01] = "The command is not supported"
errors[0x02] = "The command is not recognised" errors[0x02] = "The command is not recognised"
errors[0x03] = "The option is not supported." errors[0x03] = "The option is not supported."
errors[0x0f] = "Unknown error." errors[0x0f] = "Unknown error."
errors[0x10] = "The specified block is not available (doesnt exist)." errors[0x10] = "The specified block is not available (doesnt exist)."
errors[0x11] = "The specified block is already -locked and thus cannot be locked again" errors[0x11] = "The specified block is already -locked and thus cannot be locked again"
errors[0x12] = "The specified block is locked and its content cannot be changed." errors[0x12] = "The specified block is locked and its content cannot be changed."
errors[0x13] = "The specified block was not successfully programmed." errors[0x13] = "The specified block was not successfully programmed."
errors[0x14] = "The specified block was not successfully locked." errors[0x14] = "The specified block was not successfully locked."
return errors[number] or "Reserved for Future Use or Custom command error." return errors[number] or "Reserved for Future Use or Custom command error."
end end
local function parse15693(data) local function parse15693(data)
local bytes = utils.ConvertAsciiToBytes(data) local bytes = utils.ConvertAsciiToBytes(data)
local tmp = utils.ConvertAsciiToHex(data) local tmp = utils.ConvertAsciiToHex(data)
-- define ISO15_CRC_CHECK 0F47
local crcStr = utils.Crc15(tmp, #tmp)
if string.sub(crcStr, #crcStr - 3) ~= '470F' then -- define ISO15_CRC_CHECK 0F47
print("CRC", crc ) local crcStr = utils.Crc15(tmp, #tmp)
return nil, "CRC failed"
end
if bytes[1] % 2 == 1 then if string.sub(crcStr, #crcStr - 3) ~= '470F' then
-- Above is a poor-mans bit check: print("CRC", crc )
-- recv[0] & ISO15_RES_ERROR //(0x01) return nil, "CRC failed"
local err = "Tag returned error %i: %s" end
err = string.format(err, bytes[1], errorString15693(bytes[1]))
return nil, err if bytes[1] % 2 == 1 then
end -- Above is a poor-mans bit check:
local uid = utils.ConvertBytesToHex( bytes, true ) -- recv[0] & ISO15_RES_ERROR //(0x01)
uid = uid:sub(5, #uid-4) local err = "Tag returned error %i: %s"
return { uid = uid, } err = string.format(err, bytes[1], errorString15693(bytes[1]))
return nil, err
end
local uid = utils.ConvertBytesToHex( bytes, true )
uid = uid:sub(5, #uid-4)
return { uid = uid, }
end end
-- This function does a connect and retrieves som info -- This function does a connect and retrieves som info
@ -83,62 +83,62 @@ local function read15693(slow, dont_readresponse)
--[[ --[[
We start by trying this command: We start by trying this command:
MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one):
pm3> hf 15 info u
UID=E007C1A257394244
Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit
pm3>
From which we obtain less information than the above one.
"260100" means
0x26
-- #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
0x01
inventory
0x00
--]]
local command, result, info, err, data pm3> hf 15 info u
UID=E007C1A257394244
Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit
pm3>
data = utils.Crc15("260100") From which we obtain less information than the above one.
command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, "260100" means
arg1 = #data / 2, 0x26
arg2 = 1, -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK)
arg3 = 1, -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate
data = data} -- #define ISO15_REQ_NONINVENTORY 0x00
0x01
if slow then inventory
command.arg2 = 0 0x00
end
if dont_readresponse then --]]
command.arg3 = 0
end local command, result, info, err, data
local result, err = sendToDevice(command, dont_readresponse) data = utils.Crc15("260100")
if not result then
print(err) command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND,
return nil, "15693 identify: no answer" arg1 = #data / 2,
end arg2 = 1,
arg3 = 1,
local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result) data = data}
if len > 0 then
data = string.sub(result, count, count+len-1) if slow then
info, err = parse15693(data) command.arg2 = 0
if err then end
print(err) if dont_readresponse then
return nil, err command.arg3 = 0
end end
return info
else local result, err = sendToDevice(command, dont_readresponse)
return nil, "Failed to get response" if not result then
end print(err)
return nil, "15693 identify: no answer"
end
local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result)
if len > 0 then
data = string.sub(result, count, count+len-1)
info, err = parse15693(data)
if err then
print(err)
return nil, err
end
return info
else
return nil, "Failed to get response"
end
end end
--- ---
@ -146,19 +146,19 @@ end
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function waitFor15693() local function waitFor15693()
print("Waiting for card... press any key to quit") print("Waiting for card... press any key to quit")
while not core.ukbhit() do while not core.ukbhit() do
res, err = read15693() res, err = read15693()
if res then return res end if res then return res end
-- err means that there was no response from card -- err means that there was no response from card
end end
return nil, "Aborted by user" return nil, "Aborted by user"
end end
local library = { local library = {
read = read15693, read = read15693,
waitFor15693 = waitFor15693, waitFor15693 = waitFor15693,
parse15693 = parse15693, parse15693 = parse15693,
sendToDevice = sendToDevice, sendToDevice = sendToDevice,
} }
return library return library

View file

@ -109,16 +109,16 @@ m[0x6B]='ISSM France'
m[0x6C]='Wisesec Ltd Israel' m[0x6C]='Wisesec Ltd Israel'
m[0x7C]='DB HiTek Co Ltd Korea' m[0x7C]='DB HiTek Co Ltd Korea'
m[0x7D]='SATO Vicinity Australia' m[0x7D]='SATO Vicinity Australia'
m[0x7E]='Holtek Taiwan' m[0x7E]='Holtek Taiwan'
return { return {
lookupManufacturer = function (value) lookupManufacturer = function (value)
if type(value) == 'string' then if type(value) == 'string' then
local v = tonumber(value, 16) local v = tonumber(value, 16)
print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v)) print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v))
value = v value = v
end end
return m[value] or "no tag-info available" return m[value] or "no tag-info available"
end, end,
} }

View file

@ -1,430 +1,430 @@
--[[ --[[
This may be moved to a separate library at some point (Holiman) This may be moved to a separate library at some point (Holiman)
--]] --]]
local Utils = local Utils =
{ {
-- Asks the user for Yes or No -- Asks the user for Yes or No
confirm = function(message, ...) confirm = function(message, ...)
local answer local answer
message = message .. " [y/n] ?" message = message .. " [y/n] ?"
repeat repeat
io.write(message) io.write(message)
io.flush() io.flush()
answer = io.read() answer = io.read()
if answer == 'Y' or answer == "y" then if answer == 'Y' or answer == "y" then
return true return true
elseif answer == 'N' or answer == 'n' then elseif answer == 'N' or answer == 'n' then
return false return false
end end
until false until false
end, end,
--- ---
-- Asks the user for input -- Asks the user for input
input = function (message , default) input = function (message , default)
local answer local answer
if default ~= nil then if default ~= nil then
message = message .. " (default: ".. default.. " )" message = message .. " (default: ".. default.. " )"
end end
message = message .." \n > " message = message .." \n > "
io.write(message) io.write(message)
io.flush() io.flush()
answer = io.read() answer = io.read()
if answer == '' then answer = default end if answer == '' then answer = default end
return answer return answer
end, end,
------------ FILE READING ------------ FILE READING
ReadDumpFile = function (filename) ReadDumpFile = function (filename)
filename = filename or 'dumpdata.bin' filename = filename or 'dumpdata.bin'
if #filename == 0 then if #filename == 0 then
return nil, 'Filename length is zero' return nil, 'Filename length is zero'
end end
infile = io.open(filename, "rb") infile = io.open(filename, "rb")
if infile == nil then if infile == nil then
return nil, string.format("Could not read file %s",filename) return nil, string.format("Could not read file %s",filename)
end end
local t = infile:read("*all") local t = infile:read("*all")
io.close(infile) io.close(infile)
len = string.len(t) len = string.len(t)
local _,hex = bin.unpack(("H%d"):format(len),t) local _,hex = bin.unpack(("H%d"):format(len),t)
return hex return hex
end, end,
------------ FILE WRITING (EML) ------------ FILE WRITING (EML)
--- Writes an eml-file. --- Writes an eml-file.
-- @param uid - the uid of the tag. Used in filename -- @param uid - the uid of the tag. Used in filename
-- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
-- that is, blockData[row] contains a string with the actual data, not ascii hex representation -- that is, blockData[row] contains a string with the actual data, not ascii hex representation
-- return filename if all went well, -- return filename if all went well,
-- @reurn nil, error message if unsuccessfulls -- @reurn nil, error message if unsuccessfulls
WriteDumpFile = function(uid, blockData) WriteDumpFile = function(uid, blockData)
local destination = string.format("%s.eml", uid) local destination = string.format("%s.eml", uid)
local file = io.open(destination, "w") local file = io.open(destination, "w")
if file == nil then if file == nil then
return nil, string.format("Could not write to file %s", destination) return nil, string.format("Could not write to file %s", destination)
end end
local rowlen = string.len(blockData[1]) local rowlen = string.len(blockData[1])
for i,block in ipairs(blockData) do for i,block in ipairs(blockData) do
if rowlen ~= string.len(block) then if rowlen ~= string.len(block) then
prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
end end
local formatString = string.format("H%d", string.len(block)) local formatString = string.format("H%d", string.len(block))
local _,hex = bin.unpack(formatString,block) local _,hex = bin.unpack(formatString,block)
file:write(hex.."\n") file:write(hex.."\n")
end end
file:close() file:close()
return destination return destination
end, end,
------------ string split function ------------ string split function
Split = function( inSplitPattern, outResults ) Split = function( inSplitPattern, outResults )
if not outResults then if not outResults then
outResults = {} outResults = {}
end end
local start = 1 local start = 1
local splitStart, splitEnd = string.find( self, inSplitPattern, start ) local splitStart, splitEnd = string.find( self, inSplitPattern, start )
while splitStart do while splitStart do
table.insert( outResults, string.sub( self, start, splitStart-1 ) ) table.insert( outResults, string.sub( self, start, splitStart-1 ) )
start = splitEnd + 1 start = splitEnd + 1
splitStart, splitEnd = string.find( self, inSplitPattern, start ) splitStart, splitEnd = string.find( self, inSplitPattern, start )
end end
table.insert( outResults, string.sub( self, start ) ) table.insert( outResults, string.sub( self, start ) )
return outResults return outResults
end, end,
----ISO14443-B CRC ----ISO14443-B CRC
Crc14b = function(s) Crc14b = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
return utils.ConvertAsciiToHex( return utils.ConvertAsciiToHex(
core.iso14443b_crc(s) core.iso14443b_crc(s)
) )
end end
return nil return nil
end, end,
----ISO15693 CRC ----ISO15693 CRC
Crc15 = function(s) Crc15 = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
return utils.ConvertAsciiToHex( return utils.ConvertAsciiToHex(
core.iso15693_crc(s) core.iso15693_crc(s)
) )
end end
return nil return nil
end, end,
------------ CRC-8 Legic checksums ------------ CRC-8 Legic checksums
-- Takes a hex string and calculates a crc8 -- Takes a hex string and calculates a crc8
Crc8Legic = function(s) Crc8Legic = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
local asc = utils.ConvertHexToAscii(s) local asc = utils.ConvertHexToAscii(s)
local hash = core.crc8legic(asc) local hash = core.crc8legic(asc)
return hash return hash
end end
return nil return nil
end, end,
------------ CRC-16 ccitt checksums ------------ CRC-16 ccitt checksums
-- Takes a hex string and calculates a crc16 -- Takes a hex string and calculates a crc16
Crc16 = function(s) Crc16 = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
local asc = utils.ConvertHexToAscii(s) local asc = utils.ConvertHexToAscii(s)
local hash = core.crc16(asc) local hash = core.crc16(asc)
return hash return hash
end end
return nil return nil
end, end,
------------ CRC-64 ecma checksums ------------ CRC-64 ecma checksums
-- Takes a hex string and calculates a crc64 ecma hash -- Takes a hex string and calculates a crc64 ecma hash
Crc64 = function(s) Crc64 = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
local asc = utils.ConvertHexToAscii(s) local asc = utils.ConvertHexToAscii(s)
local hash = core.crc64(asc) local hash = core.crc64(asc)
return hash return hash
end end
return nil return nil
end, end,
------------ CRC-64 ecma 182 checksums ------------ CRC-64 ecma 182 checksums
-- Takes a hex string and calculates a crc64 ecma182 hash -- Takes a hex string and calculates a crc64 ecma182 hash
Crc64_ecma182 = function(s) Crc64_ecma182 = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
local asc = utils.ConvertHexToAscii(s) local asc = utils.ConvertHexToAscii(s)
local hash = core.crc64_ecma182(asc) local hash = core.crc64_ecma182(asc)
return hash return hash
end end
return nil return nil
end, end,
------------ SHA1 hash ------------ SHA1 hash
-- Takes a string and calculates a SHA1 hash -- Takes a string and calculates a SHA1 hash
Sha1 = function(s) Sha1 = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
return core.sha1(s) return core.sha1(s)
end end
return nil return nil
end, end,
-- Takes a hex string and calculates a SHA1 hash -- Takes a hex string and calculates a SHA1 hash
Sha1Hex = function(s) Sha1Hex = function(s)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return nil end if #s == 0 then return nil end
if type(s) == 'string' then if type(s) == 'string' then
local utils = require('utils') local utils = require('utils')
local asc = utils.ConvertHexToAscii(s) local asc = utils.ConvertHexToAscii(s)
local hash = core.sha1(asc) local hash = core.sha1(asc)
return hash return hash
end end
return nil return nil
end, end,
-- input parameter is a string -- input parameter is a string
-- Swaps the endianess and returns a number, -- Swaps the endianess and returns a number,
-- IE: 'cd7a' -> '7acd' -> 0x7acd -- IE: 'cd7a' -> '7acd' -> 0x7acd
SwapEndianness = function(s, len) SwapEndianness = function(s, len)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return '' end if #s == 0 then return '' end
if type(s) ~= 'string' then return nil end if type(s) ~= 'string' then return nil end
local retval = 0 local retval = 0
if len == 16 then if len == 16 then
local t = s:sub(3,4)..s:sub(1,2) local t = s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16) retval = tonumber(t,16)
elseif len == 24 then elseif len == 24 then
local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16) retval = tonumber(t,16)
elseif len == 32 then elseif len == 32 then
local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16) retval = tonumber(t,16)
end end
return retval return retval
end, end,
-- input parameter is a string -- input parameter is a string
-- Swaps the endianess and returns a string, -- Swaps the endianess and returns a string,
-- IE: 'cd7a' -> '7acd' -> 0x7acd -- IE: 'cd7a' -> '7acd' -> 0x7acd
SwapEndiannessStr = function(s, len) SwapEndiannessStr = function(s, len)
if s == nil then return nil end if s == nil then return nil end
if #s == 0 then return '' end if #s == 0 then return '' end
if type(s) ~= 'string' then return nil end if type(s) ~= 'string' then return nil end
local retval local retval
if len == 16 then if len == 16 then
retval = s:sub(3,4)..s:sub(1,2) retval = s:sub(3,4)..s:sub(1,2)
elseif len == 24 then elseif len == 24 then
retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
elseif len == 32 then elseif len == 32 then
retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
end end
return retval return retval
end, end,
------------ CONVERSIONS ------------ CONVERSIONS
-- --
-- Converts DECIMAL to HEX -- Converts DECIMAL to HEX
ConvertDecToHex = function(IN) ConvertDecToHex = function(IN)
local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0 local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0
while IN > 0 do while IN > 0 do
I = I+1 I = I+1
IN, D = math.floor(IN/B), math.modf(IN, B) + 1 IN, D = math.floor(IN/B), math.modf(IN, B) + 1
OUT = string.sub(K, D, D)..OUT OUT = string.sub(K, D, D)..OUT
end end
return OUT return OUT
end, end,
--- ---
-- Convert Byte array to string of hex -- Convert Byte array to string of hex
ConvertBytesToHex = function(bytes, reverse) ConvertBytesToHex = function(bytes, reverse)
if bytes == nil then return '' end if bytes == nil then return '' end
if #bytes == 0 then return '' end if #bytes == 0 then return '' end
local s={} local s={}
if reverse then if reverse then
local j=1 local j=1
for i = #bytes, 1, -1 do for i = #bytes, 1, -1 do
s[i] = string.format("%02X", bytes[j]) s[i] = string.format("%02X", bytes[j])
j = j + 1 j = j + 1
end end
else else
for i = 1, #bytes do for i = 1, #bytes do
s[i] = string.format("%02X", bytes[i]) s[i] = string.format("%02X", bytes[i])
end end
end end
return table.concat(s) return table.concat(s)
end, end,
-- Convert byte array to string with ascii -- Convert byte array to string with ascii
ConvertBytesToAscii = function(bytes) ConvertBytesToAscii = function(bytes)
if bytes == nil then return '' end if bytes == nil then return '' end
if #bytes == 0 then return '' end if #bytes == 0 then return '' end
local s={} local s={}
for i = 1, #(bytes) do for i = 1, #(bytes) do
s[i] = string.char(bytes[i]) s[i] = string.char(bytes[i])
end end
return table.concat(s) return table.concat(s)
end, end,
ConvertHexToBytes = function(s) ConvertHexToBytes = function(s)
local t={} local t={}
if s == nil then return t end if s == nil then return t end
if #s == 0 then return t end if #s == 0 then return t end
for k in s:gmatch"(%x%x)" do for k in s:gmatch"(%x%x)" do
table.insert(t,tonumber(k,16)) table.insert(t,tonumber(k,16))
end end
return t return t
end, end,
ConvertAsciiToBytes = function(s, reverse) ConvertAsciiToBytes = function(s, reverse)
local t = {} local t = {}
if s == nil then return t end if s == nil then return t end
if #s == 0 then return t end if #s == 0 then return t end
for k in s:gmatch"(.)" do for k in s:gmatch"(.)" do
table.insert(t, string.byte(k)) table.insert(t, string.byte(k))
end end
if not reverse then if not reverse then
return t return t
end end
local rev = {} local rev = {}
if reverse then if reverse then
for i = #t, 1,-1 do for i = #t, 1,-1 do
table.insert(rev, t[i] ) table.insert(rev, t[i] )
end end
end end
return rev return rev
end, end,
ConvertHexToAscii = function(s, useSafechars) ConvertHexToAscii = function(s, useSafechars)
if s == nil then return '' end if s == nil then return '' end
if #s == 0 then return '' end if #s == 0 then return '' end
local t={} local t={}
for k in s:gmatch"(%x%x)" do for k in s:gmatch"(%x%x)" do
local n = tonumber(k,16) local n = tonumber(k,16)
local c local c
if useSafechars and ( (n < 32) or (n == 127) ) then if useSafechars and ( (n < 32) or (n == 127) ) then
c = '.'; c = '.';
else else
c = string.char(n) c = string.char(n)
end end
table.insert(t,c) table.insert(t,c)
end end
return table.concat(t) return table.concat(t)
end, end,
ConvertAsciiToHex = function(s) ConvertAsciiToHex = function(s)
if s == nil then return '' end if s == nil then return '' end
if #s == 0 then return '' end if #s == 0 then return '' end
local t={} local t={}
for k in s:gmatch"(.)" do for k in s:gmatch"(.)" do
table.insert(t, string.format("%02X", string.byte(k))) table.insert(t, string.format("%02X", string.byte(k)))
end end
return table.concat(t) return table.concat(t)
end, end,
hexlify = function(s) hexlify = function(s)
local u = require('utils') local u = require('utils')
return u.ConvertAsciiToHex(s) return u.ConvertAsciiToHex(s)
end, end,
Chars2num = function(s) Chars2num = function(s)
return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4)) return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
end, end,
-- use length of string to determine 8,16,32,64 bits -- use length of string to determine 8,16,32,64 bits
bytes_to_int = function(str,endian,signed) bytes_to_int = function(str,endian,signed)
local t = {str:byte(1, -1)} local t = {str:byte(1, -1)}
if endian == "big" then --reverse bytes if endian == "big" then --reverse bytes
local tt = {} local tt = {}
for k = 1, #t do for k = 1, #t do
tt[#t-k+1] = t[k] tt[#t-k+1] = t[k]
end end
t = tt t = tt
end end
local n = 0 local n = 0
for k = 1, #t do for k = 1, #t do
n = n + t[k] * 2^((k-1) * 8) n = n + t[k] * 2^((k-1) * 8)
end end
if signed then if signed then
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative. n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
end end
return n return n
end, end,
-- a simple implementation of a sleep command. Thanks to Mosci -- a simple implementation of a sleep command. Thanks to Mosci
-- takes number of seconds to sleep -- takes number of seconds to sleep
Sleep = function(n) Sleep = function(n)
local clock = os.clock local clock = os.clock
local t0 = clock() local t0 = clock()
while clock() - t0 <= n do end while clock() - t0 <= n do end
return nil return nil
end, end,
-- function convertStringToBytes(str) -- function convertStringToBytes(str)
-- local bytes = {} -- local bytes = {}
-- local strLength = string.len(str) -- local strLength = string.len(str)
-- for i=1,strLength do -- for i=1,strLength do
-- table.insert(bytes, string.byte(str, i)) -- table.insert(bytes, string.byte(str, i))
-- end -- end
-- return bytes -- return bytes
-- end -- end
-- function convertBytesToString(bytes) -- function convertBytesToString(bytes)
-- local bytesLength = table.getn(bytes) -- local bytesLength = table.getn(bytes)
-- local str = "" -- local str = ""
-- for i=1,bytesLength do -- for i=1,bytesLength do
-- str = str .. string.char(bytes[i]) -- str = str .. string.char(bytes[i])
-- end -- end
-- return str -- return str
-- end -- end
-- function convertHexStringToBytes(str) -- function convertHexStringToBytes(str)
-- local bytes = {} -- local bytes = {}
-- local strLength = string.len(str) -- local strLength = string.len(str)
-- for k=2,strLength,2 do -- for k=2,strLength,2 do
-- local hexString = "0x" .. string.sub(str, (k - 1), k) -- local hexString = "0x" .. string.sub(str, (k - 1), k)
-- table.insert(bytes, hex.to_dec(hexString)) -- table.insert(bytes, hex.to_dec(hexString))
-- end -- end
-- return bytes -- return bytes
-- end -- end
-- function convertBytesToHexString(bytes) -- function convertBytesToHexString(bytes)
-- local str = "" -- local str = ""
-- local bytesLength = table.getn(bytes) -- local bytesLength = table.getn(bytes)
-- for i=1,bytesLength do -- for i=1,bytesLength do
-- local hexString = string.sub(hex.to_hex(bytes[i]), 3) -- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
-- if string.len(hexString) == 1 then -- if string.len(hexString) == 1 then
-- hexString = "0" .. hexString -- hexString = "0" .. hexString
-- end -- end
-- str = str .. hexString -- str = str .. hexString
-- end -- end
-- return str -- return str
-- end -- end
} }
return Utils return Utils