]> git.zerfleddert.de Git - proxmark3-svn/blob - armsrc/mifaredesfire.c
chg: LF t55xx trace
[proxmark3-svn] / armsrc / mifaredesfire.c
1 #include "mifaredesfire.h"
2
3 #define MAX_APPLICATION_COUNT 28
4 #define MAX_FILE_COUNT 16
5 #define MAX_FRAME_SIZE 60
6 #define NOT_YET_AUTHENTICATED 255
7 #define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)
8
9 // the block number for the ISO14443-4 PCB
10 uint8_t pcb_blocknum = 0;
11 // Deselect card by sending a s-block. the crc is precalced for speed
12 static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
13
14 //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
15 /* PCB CID CMD PAYLOAD */
16 //static uint8_t __res[MAX_FRAME_SIZE];
17
18 bool InitDesfireCard(){
19
20 // Make sure it is off.
21 // FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
22 // SpinDelay(300);
23
24 byte_t cardbuf[USB_CMD_DATA_SIZE];
25 memset(cardbuf,0,sizeof(cardbuf));
26
27 iso14a_set_tracing(TRUE);
28 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
29
30 iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
31 int len = iso14443a_select_card(NULL,card,NULL);
32
33 if (!len) {
34 if (MF_DBGLEVEL >= 1) {
35 Dbprintf("Can't select card");
36 }
37 OnError();
38 return false;
39 }
40 return true;
41 }
42
43 // ARG0 flag enums
44 enum {
45 NONE = 0x00,
46 INIT = 0x01,
47 DISCONNECT = 0x02,
48 CLEARTRACE = 0x04,
49 BAR = 0x08,
50 } CmdOptions ;
51
52 void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
53
54 /* ARG0 contains flags.
55 0x01 = init card.
56 0x02 = Disconnect
57 0x03
58 */
59 uint8_t flags = arg0;
60 size_t datalen = arg1;
61 uint8_t resp[RECV_RES_SIZE];
62 memset(resp,0,sizeof(resp));
63
64 if (MF_DBGLEVEL >= 4) {
65 Dbprintf(" flags : %02X", flags);
66 Dbprintf(" len : %02X", datalen);
67 print_result(" RX : ", datain, datalen);
68 }
69
70 if ( flags & CLEARTRACE ){
71 iso14a_clear_trace();
72 }
73
74 if ( flags & INIT ){
75 if ( !InitDesfireCard() )
76 return;
77 }
78
79 int len = DesfireAPDU(datain, datalen, resp);
80 if (MF_DBGLEVEL >= 4) {
81 print_result("ERR <--: ", resp, len);
82 }
83
84 if ( !len ) {
85 OnError();
86 return;
87 }
88
89 // reset the pcb_blocknum,
90 pcb_blocknum = 0;
91
92 if ( flags & DISCONNECT ){
93 OnSuccess();
94 }
95
96 cmd_send(CMD_ACK,1,len,0,resp,len);
97 }
98
99 void MifareDesfireGetInformation(){
100
101 int len = 0;
102 uint8_t resp[USB_CMD_DATA_SIZE];
103 uint8_t dataout[USB_CMD_DATA_SIZE];
104 byte_t cardbuf[USB_CMD_DATA_SIZE];
105
106 memset(resp,0,sizeof(resp));
107 memset(dataout,0, sizeof(dataout));
108 memset(cardbuf,0,sizeof(cardbuf));
109
110 /*
111 1 = PCB 1
112 2 = cid 2
113 3 = desfire command 3
114 4-5 = crc 4 key
115 5-6 crc
116 PCB == 0x0A because sending CID byte.
117 CID == 0x00 first card?
118 */
119 iso14a_clear_trace();
120 iso14a_set_tracing(TRUE);
121 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
122
123 // card select - information
124 iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
125 byte_t isOK = iso14443a_select_card(NULL, card, NULL);
126 if (isOK != 1) {
127 if (MF_DBGLEVEL >= 1) {
128 Dbprintf("Can't select card");
129 }
130 OnError();
131 return;
132 }
133
134 memcpy(dataout,card->uid,7);
135
136 LED_A_ON();
137 LED_B_OFF();
138 LED_C_OFF();
139
140 uint8_t cmd[] = {GET_VERSION};
141 size_t cmd_len = sizeof(cmd);
142
143 len = DesfireAPDU(cmd, cmd_len, resp);
144 if ( !len ) {
145 print_result("ERROR <--: ", resp, len);
146 OnError();
147 return;
148 }
149
150 LED_A_OFF();
151 LED_B_ON();
152 memcpy(dataout+7,resp+3,7);
153
154 // ADDITION_FRAME 1
155 cmd[0] = ADDITIONAL_FRAME;
156 len = DesfireAPDU(cmd, cmd_len, resp);
157 if ( !len ) {
158 print_result("ERROR <--: ", resp, len);
159 OnError();
160 return;
161 }
162
163 LED_B_OFF();
164 LED_C_ON();
165 memcpy(dataout+7+7,resp+3,7);
166
167 // ADDITION_FRAME 2
168 len = DesfireAPDU(cmd, cmd_len, resp);
169 if ( !len ) {
170 print_result("ERROR <--: ", resp, len);
171 OnError();
172 return;
173 }
174
175 memcpy(dataout+7+7+7,resp+3,14);
176
177 cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
178
179 // reset the pcb_blocknum,
180 pcb_blocknum = 0;
181 OnSuccess();
182 }
183
184 void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
185
186 int len = 0;
187 //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
188 uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
189 //uint8_t null_key_data8[8] = {0x00};
190 //uint8_t null_key_data16[16] = {0x00};
191 //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
192 //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
193
194 //uint8_t* bigbuffer = mifare_get_bigbufptr();
195 uint8_t resp[256] = {0x00};
196 uint8_t IV[16] = {0x00};
197
198 size_t datalen = datain[0];
199
200 uint8_t cmd[40] = {0x00};
201 uint8_t encRndB[16] = {0x00};
202 uint8_t decRndB[16] = {0x00};
203 uint8_t nonce[16] = {0x00};
204 uint8_t both[32] = {0x00};
205 uint8_t encBoth[32] = {0x00};
206
207 InitDesfireCard();
208
209 LED_A_ON();
210 LED_B_OFF();
211 LED_C_OFF();
212
213 // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
214 // 4 olika crypto algo DES, 3DES, 3K3DES, AES
215 // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
216
217 // des, nyckel 0,
218 switch (mode){
219 case 1:
220 // if ( SendDesfireCommand(AUTHENTICATE, &keyno, resp) > 0 ){
221 // // fick nonce från kortet
222 // }
223 break;
224 case 2:
225 //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
226 break;
227 case 3:{
228
229 //defaultkey
230 uint8_t keybytes[16];
231 if (datain[1] == 0xff){
232 memcpy(keybytes,PICC_MASTER_KEY16,16);
233 } else{
234 memcpy(keybytes, datain+1, datalen);
235 }
236
237 struct desfire_key defaultkey = {0};
238 desfirekey_t key = &defaultkey;
239 Desfire_aes_key_new( keybytes, key);
240
241 AesCtx ctx;
242 if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
243 if( MF_DBGLEVEL >= 4) {
244 Dbprintf("AES context failed to init");
245 }
246 OnError();
247 return;
248 }
249
250 cmd[0] = AUTHENTICATE_AES;
251 cmd[1] = 0x00; //keynumber
252 len = DesfireAPDU(cmd, 2, resp);
253 if ( !len ) {
254 if (MF_DBGLEVEL >= 1) {
255 DbpString("Authentication failed. Card timeout.");
256 }
257 OnError();
258 return;
259 }
260
261 memcpy( encRndB, resp+3, 16);
262
263 // dekryptera tagnonce.
264 AesDecrypt(&ctx, encRndB, decRndB, 16);
265 rol(decRndB,16);
266 memcpy(both, nonce,16);
267 memcpy(both+16, decRndB ,16 );
268 AesEncrypt(&ctx, both, encBoth, 32 );
269
270 cmd[0] = ADDITIONAL_FRAME;
271 memcpy(cmd+1, encBoth, 32 );
272
273 len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
274 if ( !len ) {
275 if (MF_DBGLEVEL >= 1) {
276 DbpString("Authentication failed. Card timeout.");
277 }
278 OnError();
279 return;
280 }
281
282 if ( resp[2] == 0x00 ){
283 // Create AES Session key
284 struct desfire_key sessionKey = {0};
285 desfirekey_t skey = &sessionKey;
286 Desfire_session_key_new( nonce, decRndB , key, skey );
287 print_result("SESSION : ", skey->data, 16);
288 } else {
289 DbpString("Authetication failed.");
290 OnError();
291 return;
292 }
293
294 break;
295 }
296 }
297
298 OnSuccess();
299 cmd_send(CMD_ACK,1,len,0,resp,len);
300 }
301
302 // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
303 // cmd = cmd bytes to send
304 // cmd_len = length of cmd
305 // dataout = pointer to response data array
306 int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
307
308 uint32_t status = 0;
309 size_t wrappedLen = 0;
310 uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
311
312 wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
313
314 if (MF_DBGLEVEL >= 4) {
315 print_result("WCMD <--: ", wCmd, wrappedLen);
316 }
317 ReaderTransmit( wCmd, wrappedLen, NULL);
318
319 status = ReaderReceive(dataout);
320
321 if( status == 0x00){
322 if (MF_DBGLEVEL >= 4) {
323 Dbprintf("fukked");
324 }
325 return FALSE; //DATA LINK ERROR
326 }
327 // if we received an I- or R(ACK)-Block with a block number equal to the
328 // current block number, toggle the current block number
329 else if (status >= 4 // PCB+CID+CRC = 4 bytes
330 && ((dataout[0] & 0xC0) == 0 // I-Block
331 || (dataout[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
332 && (dataout[0] & 0x01) == pcb_blocknum) // equal block numbers
333 {
334 pcb_blocknum ^= 1; //toggle next block
335 }
336 return status;
337 }
338
339 // CreateAPDU
340 size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
341
342 size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
343
344 uint8_t cmd[cmdlen];
345 memset(cmd, 0, cmdlen);
346
347 cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
348 cmd[0] |= pcb_blocknum; // OR the block number into the PCB
349 cmd[1] = 0x00; // CID: 0x00 //FIXME: allow multiple selected cards
350
351 memcpy(cmd+2, datain, len);
352 AppendCrc14443a(cmd, len+2);
353
354 memcpy(dataout, cmd, cmdlen);
355
356 return cmdlen;
357 }
358
359 // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
360 // crc_update(&desfire_crc32, addr, addr_sz);
361 // crc_update(&desfire_crc32, byte, 8);
362 // uint32_t crc = crc_finish(&desfire_crc32);
363
364 void OnSuccess(){
365 pcb_blocknum = 0;
366 ReaderTransmit(deselect_cmd, 3 , NULL);
367 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
368 LEDsoff();
369 }
370
371 void OnError(){
372 pcb_blocknum = 0;
373 ReaderTransmit(deselect_cmd, 3 , NULL);
374 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
375 cmd_send(CMD_ACK,0,0,0,0,0);
376 LEDsoff();
377 }
Impressum, Datenschutz