]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/lualibs/read14b.lua
ADD: Added the HitagS from @spenneb ref:https://events.ccc.de/congress/2015/Fahrplan...
[proxmark3-svn] / client / lualibs / read14b.lua
... / ...
CommitLineData
1
2--[[
3 This is a library to read 14443b tags. It can be used something like this
4
5 local reader = require('read14b')
6 result, err = reader.select1443b()
7 if not result then
8 print(err)
9 return
10 end
11 print(result.name)
12
13--]]
14-- Loads the commands-library
15local cmds = require('commands')
16local utils = require('utils')
17local TIMEOUT = 10000 -- Shouldn't take longer than 2 seconds
18
19local function parse1443b_reqb(data)
20 --[[
21 --]]
22 local pcb = data:sub(1,2)
23 local uid = data:sub(3,10)
24 local pps = data:sub(11,18)
25 local ats = data:sub(19,24)
26 local crc = data:sub(25,29)
27 return { pcb = pcb, uid = uid, pps = pps, ats = ats, crc = crc, cid = '' }
28end
29
30local function parse1443b_attrib(data)
31 --[[
32 --]]
33 local attrib = data:sub(1,2)
34 local crc = data:sub(3,7)
35 return { attrib = attrib, crc = crc }
36end
37
38
39--- Sends a USBpacket to the device
40-- @param command - the usb packet to send
41-- @param readresponse - if set to true, we read the device answer packet
42-- which is usually recipe for fail. If not sent, the host will wait 2s for a
43-- response of type CMD_ACK
44-- @return packet,nil if successfull
45-- nil, errormessage if unsuccessfull
46local function sendToDevice(cmd, readresponse)
47 core.clearCommandBuffer()
48 local err = core.SendCommand(cmd:getBytes())
49 if err then
50 print(err)
51 return nil, err
52 end
53 if readresponse == 0 then return '',nil end
54 local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
55 if response == nil then return nil, nil end
56 return response,nil
57end
58--- Picks out and displays the data read from a tag
59-- Specifically, takes a usb packet, converts to a Command
60-- (as in commands.lua), takes the data-array and
61-- reads the number of bytes specified in arg1 (arg0 in c-struct)
62-- and displays the data
63-- @param usbpacket the data received from the device
64local function showData(usbpacket)
65 local response = Command.parse(usbpacket)
66 local len = tonumber(response.arg1) * 2
67 local data = string.sub(response.data, 0, len);
68 print("<< ",data)
69end
70
71---
72-- Sends a usbpackage , "hf 14b raw" and the 14bCrc is added to the rawdata before sending
73local function sendRaw(rawdata, readresponse, addcrc)
74 -- add crc first
75 local rawdata_crc = rawdata
76 if ( addcrc == 1) then
77 rawdata_crc = utils.Crc14b(rawdata)
78 end
79 print(">> ", rawdata_crc)
80
81 local command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
82 arg1 = #rawdata_crc/2, -- LEN of data, which is half the length of the ASCII-string rawdata
83 arg2 = readresponse, -- read response
84 arg3 = 1, -- leave power on
85 data = rawdata_crc} -- raw data bytes
86 return sendToDevice(command, readresponse)
87end
88
89-- This function does a connect and retrieves some info
90-- @return if successfull: an table containing card info
91-- @return if unsuccessfull : nil, error
92
93-- void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[])
94local function select1443b()
95
96 local result, infoReqb, infoAttrib, infoPong, err, resp, len, data
97 local goodReqbResponse = false
98 --REQB
99 local p = 5
100 while p > 0 do
101 -- 05 00 08
102 -- 05
103 -- command (REQB/WUPB)
104 -- 00
105 -- AFI application family identifier ( 00 == all sorts)
106 -- 08 (ie WUPB)
107 -- bit 0-1-2 | N slots ( 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 == 16)
108 -- bit 3 | (1== WUPB, 0 == REQB)
109 -- bit 4-5-6-7 | AFI application family identifier
110 local result, err = sendRaw('050008', 1, 1)
111 if result then
112 resp = Command.parse( result )
113 len = tonumber(resp.arg1) * 2
114 local data = string.sub(resp.data, 0, len)
115 if ( resp.arg1 == 14 ) then
116 --print ('DATA ::', data)
117 infoReqb, err = parse1443b_reqb(data)
118 --print(infoReqb.pcb, infoReqb.uid, infoReqb.pps, infoReqb.ats, infoReqb.crc)
119 goodReqbResponse = true
120 break -- break while loop. REQB got a good response
121 end
122 end
123
124 -- send some strange 0A/0C
125 if ( p < 3) then
126 sendRaw('0A', 0, 0)
127 sendRaw('0C', 0, 0)
128 end
129
130 p = p - 1
131 print('retrying')
132 end
133
134 if goodReqbResponse == false then
135 err = "No response from card"
136 print(err)
137 return nil, err
138 end
139 --SLOT MARKER
140 -- result, err = sendRaw('05', 1, 1)
141 -- if result then
142 -- showData(result)
143 -- resp = Command.parse( result )
144 -- if arg1 == 0 then
145 -- return nil, "iso14443b card - SLOT MARKER failed"
146 -- end
147 -- len = tonumber(resp.arg1) * 2
148 -- data = string.sub(resp.data, 0, len)
149 -- infoAttrib, err = parse1443b_attrib(data)
150 -- print( infoAttrib.attrib, infoAttrib.crc)
151 -- else
152 -- err ="No response from card"
153 -- print(err)
154 -- return nil, err
155 -- end
156
157 --ATTRIB
158 local cid = '00'
159 result, err = sendRaw('1D'..infoReqb.uid..'000801'..cid, 1, 1)
160 if result then
161 showData(result)
162 resp = Command.parse( result )
163 if resp.arg1 == 0 then
164 return nil, "iso14443b card - ATTRIB failed"
165 end
166 len = tonumber(resp.arg1) * 2
167 data = string.sub(resp.data, 0, len)
168 infoAttrib, err = parse1443b_attrib(data)
169 infoReqb.cid = infoAttrib.attrib:sub(2,2)
170 else
171 err ="No response from card"
172 print(err)
173 return nil, err
174 end
175
176 --PING / PONG - Custom Anticollison for Navigo.
177 local ping = ('BA00')
178 result, err = sendRaw(ping, 1, 1)
179 if result then
180 resp = Command.parse( result )
181 if arg1 == 0 then
182 return nil, "iso14443b card - PING/PONG failed"
183 end
184 showData(result)
185 else
186 err = "No response from card"
187 print(err)
188 return nil, err
189 end
190
191 return infoReqb
192end
193
194---
195-- Waits for a mifare card to be placed within the vicinity of the reader.
196-- @return if successfull: an table containing card info
197-- @return if unsuccessfull : nil, error
198local function waitFor14443b()
199 print("Waiting for card... press any key to quit")
200 while not core.ukbhit() do
201 res, err = select1443b()
202 if res then return res end
203 -- err means that there was no response from card
204 end
205 return nil, "Aborted by user"
206end
207
208local function disconnect(uid)
209
210 local halt = ('50'..uid) -- 50 UID0 UID1 UID2 UID3 CRC1 CRC2
211 result, err = sendRaw(halt, 1, 1)
212 if result then
213 resp = Command.parse( result )
214 showData(result) -- expected answer is 00 CRC1 CRC2
215 else
216 err = "No response from card"
217 print(err)
218 return nil, err
219 end
220
221 -- shutdown raw command / pm3 device.
222 local command = Command:new{ cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = 0, arg2 = 0, arg3 = 0 }
223 -- We can ignore the response here, no ACK is returned for this command
224 -- Check /armsrc/iso14443b.c, SendRawCommand14443B() for details
225 return sendToDevice(command, 0)
226end
227
228local library = {
229 select1443b = select1443b,
230 select = select1443b,
231 waitFor14443b = waitFor14443b,
232 sendToDevice = sendToDevice,
233 disconnect = disconnect,
234 sendRaw = sendRaw,
235 showData = showData,
236}
237
238return library
Impressum, Datenschutz