]> git.zerfleddert.de Git - proxmark3-svn/blob - client/lualibs/read14b.lua
49e3d0e7fe92c222c9c6f72b1dd45c0ded0415a8
[proxmark3-svn] / client / lualibs / read14b.lua
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
15 local cmds = require('commands')
16 local utils = require('utils')
17 local TIMEOUT = 10000 -- Shouldn't take longer than 2 seconds
18
19 local 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 = '' }
28 end
29
30 local 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 }
36 end
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
46 local 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
57 end
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
64 local 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)
69 end
70
71 ---
72 -- Sends a usbpackage , "hf 14b raw" and the 14bCrc is added to the rawdata before sending
73 local 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)
87 end
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[])
94 local function select1443b()
95
96 local result, infoReqb, infoAttrib, infoPong, err, resp, len, data
97 local goodReqbResponse = false
98 --REQB
99 local p = 20
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
192 end
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
198 local 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 if res == nil then return nil, err end
204 -- err means that there was no response from card
205 end
206 return nil, "Aborted by user"
207 end
208
209 local function disconnect(uid)
210
211 local halt = ('50'..uid) -- 50 UID0 UID1 UID2 UID3 CRC1 CRC2
212 result, err = sendRaw(halt, 1, 1)
213 if result then
214 resp = Command.parse( result )
215 showData(result) -- expected answer is 00 CRC1 CRC2
216 else
217 err = "No response from card"
218 print(err)
219 return nil, err
220 end
221
222 -- shutdown raw command / pm3 device.
223 local command = Command:new{ cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = 0, arg2 = 0, arg3 = 0 }
224 -- We can ignore the response here, no ACK is returned for this command
225 -- Check /armsrc/iso14443b.c, SendRawCommand14443B() for details
226 return sendToDevice(command, 0)
227 end
228
229 local library = {
230 select1443b = select1443b,
231 select = select1443b,
232 waitFor14443b = waitFor14443b,
233 sendToDevice = sendToDevice,
234 disconnect = disconnect,
235 sendRaw = sendRaw,
236 showData = showData,
237 }
238
239 return library
Impressum, Datenschutz