]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/mifaredesfire.c
CHG: 'lf cotag read' - it now follows "lf config" settings when collecting signaldata.
[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_DESFIRE_FRAME_SIZE 60
6 #define NOT_YET_AUTHENTICATED 255
7 #define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
8 #define RECEIVE_SIZE 64
9
10 // the block number for the ISO14443-4 PCB
11 uint8_t pcb_blocknum = 0;
12 // Deselect card by sending a s-block. the crc is precalced for speed
13 static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
14
15 //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
16 /* PCB CID CMD PAYLOAD */
17 //static uint8_t __res[MAX_FRAME_SIZE];
18
19 bool InitDesfireCard(){
20
21 iso14a_card_select_t card;
22
23 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
24 set_tracing(TRUE);
25
26 if (!iso14443a_select_card(NULL, &card, NULL, true, 0)) {
27 if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card");
28 OnError(1);
29 return false;
30 }
31 return true;
32 }
33
34 // ARG0 flag enums
35 enum {
36 NONE = 0x00,
37 INIT = 0x01,
38 DISCONNECT = 0x02,
39 CLEARTRACE = 0x04,
40 BAR = 0x08,
41 } CmdOptions ;
42
43 void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
44
45 /* ARG0 contains flags.
46 0x01 = init card.
47 0x02 = Disconnect
48 0x03
49 */
50 uint8_t flags = arg0;
51 size_t datalen = arg1;
52 uint8_t resp[RECEIVE_SIZE];
53 memset(resp,0,sizeof(resp));
54
55 if (MF_DBGLEVEL >= 4) {
56 Dbprintf(" flags : %02X", flags);
57 Dbprintf(" len : %02X", datalen);
58 print_result(" RX : ", datain, datalen);
59 }
60
61 if ( flags & CLEARTRACE )
62 clear_trace();
63
64 if ( flags & INIT ){
65 if ( !InitDesfireCard() )
66 return;
67 }
68
69 int len = DesfireAPDU(datain, datalen, resp);
70 if (MF_DBGLEVEL >= 4)
71 print_result("ERR <--: ", resp, len);
72
73 if ( !len ) {
74 OnError(2);
75 return;
76 }
77
78 // reset the pcb_blocknum,
79 pcb_blocknum = 0;
80
81 if ( flags & DISCONNECT )
82 OnSuccess();
83
84 cmd_send(CMD_ACK,1,len,0,resp,len);
85 }
86
87 void MifareDesfireGetInformation(){
88
89 int len = 0;
90 iso14a_card_select_t card;
91 uint8_t resp[USB_CMD_DATA_SIZE] = {0x00};
92 uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00};
93
94 /*
95 1 = PCB 1
96 2 = cid 2
97 3 = desfire command 3
98 4-5 = crc 4 key
99 5-6 crc
100 PCB == 0x0A because sending CID byte.
101 CID == 0x00 first card?
102 */
103 clear_trace();
104 set_tracing(TRUE);
105 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
106
107 // card select - information
108 if ( !iso14443a_select_card(NULL, &card, NULL, true, 0) ) {
109 if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card");
110 OnError(1);
111 return;
112 }
113
114 memcpy(dataout, card.uid, 7);
115
116 LED_A_ON();
117 LED_B_OFF();
118 LED_C_OFF();
119
120 uint8_t cmd[] = {GET_VERSION};
121 size_t cmd_len = sizeof(cmd);
122
123 len = DesfireAPDU(cmd, cmd_len, resp);
124 if ( !len ) {
125 print_result("ERROR <--: ", resp, len);
126 OnError(2);
127 return;
128 }
129
130 LED_A_OFF();
131 LED_B_ON();
132 memcpy(dataout+7,resp+3,7);
133
134 // ADDITION_FRAME 1
135 cmd[0] = ADDITIONAL_FRAME;
136 len = DesfireAPDU(cmd, cmd_len, resp);
137 if ( !len ) {
138 print_result("ERROR <--: ", resp, len);
139 OnError(2);
140 return;
141 }
142
143 LED_B_OFF();
144 LED_C_ON();
145 memcpy(dataout+7+7,resp+3,7);
146
147 // ADDITION_FRAME 2
148 len = DesfireAPDU(cmd, cmd_len, resp);
149 if ( !len ) {
150 print_result("ERROR <--: ", resp, len);
151 OnError(2);
152 return;
153 }
154
155 memcpy(dataout+7+7+7,resp+3,14);
156
157 cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
158
159 // reset the pcb_blocknum,
160 pcb_blocknum = 0;
161 OnSuccess();
162 }
163
164 void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
165
166 int len = 0;
167 //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
168 uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
169 uint8_t null_key_data8[8] = {0x00};
170 //uint8_t null_key_data16[16] = {0x00};
171 //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
172 //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
173
174 uint8_t resp[256] = {0x00};
175 uint8_t IV[16] = {0x00};
176
177 size_t datalen = datain[0];
178
179 uint8_t cmd[40] = {0x00};
180 uint8_t encRndB[16] = {0x00};
181 uint8_t decRndB[16] = {0x00};
182 uint8_t nonce[16] = {0x00};
183 uint8_t both[32] = {0x00};
184 uint8_t encBoth[32] = {0x00};
185
186 InitDesfireCard();
187
188 LED_A_ON();
189 LED_B_OFF();
190 LED_C_OFF();
191
192 // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
193 // 4 olika crypto algo DES, 3DES, 3K3DES, AES
194 // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
195
196 // des, nyckel 0,
197 switch (mode){
198 case 1:{
199 uint8_t keybytes[16];
200 uint8_t RndA[8] = {0x00};
201 uint8_t RndB[8] = {0x00};
202
203 if (algo == 2) {
204 if (datain[1] == 0xff){
205 memcpy(keybytes,PICC_MASTER_KEY16,16);
206 } else {
207 memcpy(keybytes, datain+1, datalen);
208 }
209 } else {
210 if (algo == 1) {
211 if (datain[1] == 0xff){
212 memcpy(keybytes,null_key_data8,8);
213 } else{
214 memcpy(keybytes, datain+1, datalen);
215 }
216 }
217 }
218
219 struct desfire_key defaultkey = {0};
220 desfirekey_t key = &defaultkey;
221
222 if (algo == 2)
223 Desfire_3des_key_new_with_version(keybytes, key);
224 else if (algo ==1)
225 Desfire_des_key_new(keybytes, key);
226
227 cmd[0] = AUTHENTICATE;
228 cmd[1] = keyno; //keynumber
229 len = DesfireAPDU(cmd, 2, resp);
230 if ( !len ) {
231 if (MF_DBGLEVEL >= MF_DBG_ERROR) {
232 DbpString("Authentication failed. Card timeout.");
233 }
234 OnError(3);
235 return;
236 }
237
238 if ( resp[2] == 0xaf ){
239 } else {
240 DbpString("Authetication failed. Invalid key number.");
241 OnError(3);
242 return;
243 }
244
245 memcpy( encRndB, resp+3, 8);
246 if (algo == 2)
247 tdes_dec(&decRndB, &encRndB, key->data);
248 else if (algo == 1)
249 des_dec(&decRndB, &encRndB, key->data);
250
251 memcpy(RndB, decRndB, 8);
252 rol(decRndB,8);
253
254 // This should be random
255 uint8_t decRndA[8] = {0x00};
256 memcpy(RndA, decRndA, 8);
257 uint8_t encRndA[8] = {0x00};
258
259 if (algo == 2)
260 tdes_dec(&encRndA, &decRndA, key->data);
261 else if (algo == 1)
262 des_dec(&encRndA, &decRndA, key->data);
263
264 memcpy(both, encRndA, 8);
265
266 for (int x = 0; x < 8; x++) {
267 decRndB[x] = decRndB[x] ^ encRndA[x];
268
269 }
270
271 if (algo == 2)
272 tdes_dec(&encRndB, &decRndB, key->data);
273 else if (algo == 1)
274 des_dec(&encRndB, &decRndB, key->data);
275
276 memcpy(both + 8, encRndB, 8);
277
278 cmd[0] = ADDITIONAL_FRAME;
279 memcpy(cmd+1, both, 16 );
280
281 len = DesfireAPDU(cmd, 17, resp);
282 if ( !len ) {
283 if (MF_DBGLEVEL >= MF_DBG_ERROR) {
284 DbpString("Authentication failed. Card timeout.");
285 }
286 OnError(3);
287 return;
288 }
289
290 if ( resp[2] == 0x00 ){
291
292 struct desfire_key sessionKey = {0};
293 desfirekey_t skey = &sessionKey;
294 Desfire_session_key_new( RndA, RndB , key, skey );
295 //print_result("SESSION : ", skey->data, 8);
296
297 memcpy(encRndA, resp+3, 8);
298
299 if (algo == 2)
300 tdes_dec(&encRndA, &encRndA, key->data);
301 else if (algo == 1)
302 des_dec(&encRndA, &encRndA, key->data);
303
304 rol(decRndA,8);
305 for (int x = 0; x < 8; x++) {
306 if (decRndA[x] != encRndA[x]) {
307 DbpString("Authetication failed. Cannot varify PICC.");
308 OnError(4);
309 return;
310 }
311 }
312
313 //Change the selected key to a new value.
314 /*
315
316 // Current key is a 3DES key, change it to a DES key
317 if (algo == 2) {
318 cmd[0] = CHANGE_KEY;
319 cmd[1] = keyno;
320
321 uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
322
323 uint8_t first, second;
324 uint8_t buff1[8] = {0x00};
325 uint8_t buff2[8] = {0x00};
326 uint8_t buff3[8] = {0x00};
327
328 memcpy(buff1,newKey, 8);
329 memcpy(buff2,newKey + 8, 8);
330
331 ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
332 memcpy(buff3, &first, 1);
333 memcpy(buff3 + 1, &second, 1);
334
335 tdes_dec(&buff1, &buff1, skey->data);
336 memcpy(cmd+2,buff1,8);
337
338 for (int x = 0; x < 8; x++) {
339 buff2[x] = buff2[x] ^ buff1[x];
340 }
341 tdes_dec(&buff2, &buff2, skey->data);
342 memcpy(cmd+10,buff2,8);
343
344 for (int x = 0; x < 8; x++) {
345 buff3[x] = buff3[x] ^ buff2[x];
346 }
347 tdes_dec(&buff3, &buff3, skey->data);
348 memcpy(cmd+18,buff3,8);
349
350 // The command always times out on the first attempt, this will retry until a response
351 // is recieved.
352 len = 0;
353 while(!len) {
354 len = DesfireAPDU(cmd,26,resp);
355 }
356
357 } else {
358 // Current key is a DES key, change it to a 3DES key
359 if (algo == 1) {
360 cmd[0] = CHANGE_KEY;
361 cmd[1] = keyno;
362
363 uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
364
365 uint8_t first, second;
366 uint8_t buff1[8] = {0x00};
367 uint8_t buff2[8] = {0x00};
368 uint8_t buff3[8] = {0x00};
369
370 memcpy(buff1,newKey, 8);
371 memcpy(buff2,newKey + 8, 8);
372
373 ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
374 memcpy(buff3, &first, 1);
375 memcpy(buff3 + 1, &second, 1);
376
377 des_dec(&buff1, &buff1, skey->data);
378 memcpy(cmd+2,buff1,8);
379
380 for (int x = 0; x < 8; x++) {
381 buff2[x] = buff2[x] ^ buff1[x];
382 }
383 des_dec(&buff2, &buff2, skey->data);
384 memcpy(cmd+10,buff2,8);
385
386 for (int x = 0; x < 8; x++) {
387 buff3[x] = buff3[x] ^ buff2[x];
388 }
389 des_dec(&buff3, &buff3, skey->data);
390 memcpy(cmd+18,buff3,8);
391
392 // The command always times out on the first attempt, this will retry until a response
393 // is recieved.
394 len = 0;
395 while(!len) {
396 len = DesfireAPDU(cmd,26,resp);
397 }
398 }
399 }
400 */
401
402 OnSuccess();
403 if (algo == 2)
404 cmd_send(CMD_ACK,1,0,0,skey->data,16);
405 else if (algo == 1)
406 cmd_send(CMD_ACK,1,0,0,skey->data,8);
407 } else {
408 DbpString("Authetication failed.");
409 OnError(6);
410 return;
411 }
412 }
413 break;
414 case 2:
415 //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
416 break;
417 case 3:{
418
419 //defaultkey
420 uint8_t keybytes[16] = {0x00};
421 if (datain[1] == 0xff){
422 memcpy(keybytes,PICC_MASTER_KEY16,16);
423 } else{
424 memcpy(keybytes, datain+1, datalen);
425 }
426
427 struct desfire_key defaultkey = {0x00};
428 desfirekey_t key = &defaultkey;
429 Desfire_aes_key_new( keybytes, key);
430
431 AesCtx ctx;
432 if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
433 if( MF_DBGLEVEL >= 4) {
434 Dbprintf("AES context failed to init");
435 }
436 OnError(7);
437 return;
438 }
439
440 cmd[0] = AUTHENTICATE_AES;
441 cmd[1] = 0x00; //keynumber
442 len = DesfireAPDU(cmd, 2, resp);
443 if ( !len ) {
444 if (MF_DBGLEVEL >= MF_DBG_ERROR) {
445 DbpString("Authentication failed. Card timeout.");
446 }
447 OnError(3);
448 return;
449 }
450
451 memcpy( encRndB, resp+3, 16);
452
453 // dekryptera tagnonce.
454 AesDecrypt(&ctx, encRndB, decRndB, 16);
455 rol(decRndB,16);
456 memcpy(both, nonce,16);
457 memcpy(both+16, decRndB ,16 );
458 AesEncrypt(&ctx, both, encBoth, 32 );
459
460 cmd[0] = ADDITIONAL_FRAME;
461 memcpy(cmd+1, encBoth, 32 );
462
463 len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
464 if ( !len ) {
465 if (MF_DBGLEVEL >= MF_DBG_ERROR) {
466 DbpString("Authentication failed. Card timeout.");
467 }
468 OnError(3);
469 return;
470 }
471
472 if ( resp[2] == 0x00 ){
473 // Create AES Session key
474 struct desfire_key sessionKey = {0};
475 desfirekey_t skey = &sessionKey;
476 Desfire_session_key_new( nonce, decRndB , key, skey );
477 print_result("SESSION : ", skey->data, 16);
478 } else {
479 DbpString("Authetication failed.");
480 OnError(7);
481 return;
482 }
483
484 break;
485 }
486 }
487
488 OnSuccess();
489 cmd_send(CMD_ACK,1,len,0,resp,len);
490 }
491
492 // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
493 // cmd = cmd bytes to send
494 // cmd_len = length of cmd
495 // dataout = pointer to response data array
496 int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
497
498 size_t len = 0;
499 size_t wrappedLen = 0;
500 uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00};
501 uint8_t resp[MAX_FRAME_SIZE];
502 uint8_t par[MAX_PARITY_SIZE];
503
504 wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
505
506 if (MF_DBGLEVEL >= 4)
507 print_result("WCMD <--: ", wCmd, wrappedLen);
508
509 ReaderTransmit( wCmd, wrappedLen, NULL);
510
511 len = ReaderReceive(resp, par);
512 if ( !len ) {
513 if (MF_DBGLEVEL >= 4) Dbprintf("fukked");
514 return FALSE; //DATA LINK ERROR
515 }
516 // if we received an I- or R(ACK)-Block with a block number equal to the
517 // current block number, toggle the current block number
518 else if (len >= 4 // PCB+CID+CRC = 4 bytes
519 && ((resp[0] & 0xC0) == 0 // I-Block
520 || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
521 && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
522 {
523 pcb_blocknum ^= 1; //toggle next block
524 }
525
526 memcpy(dataout, resp, len);
527 return len;
528 }
529
530 // CreateAPDU
531 size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
532
533 size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
534
535 uint8_t cmd[cmdlen];
536 memset(cmd, 0, cmdlen);
537
538 cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
539 cmd[0] |= pcb_blocknum; // OR the block number into the PCB
540 cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
541
542 memcpy(cmd+2, datain, len);
543 AppendCrc14443a(cmd, len+2);
544
545 memcpy(dataout, cmd, cmdlen);
546
547 return cmdlen;
548 }
549
550 // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
551 // crc_update(&desfire_crc32, addr, addr_sz);
552 // crc_update(&desfire_crc32, byte, 8);
553 // uint32_t crc = crc_finish(&desfire_crc32);
554
555 void OnSuccess(){
556 pcb_blocknum = 0;
557 ReaderTransmit(deselect_cmd, 3 , NULL);
558 mifare_ultra_halt();
559 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
560 LEDsoff();
561 set_tracing(FALSE);
562 }
563
564 void OnError(uint8_t reason){
565 cmd_send(CMD_ACK,0,reason,0,0,0);
566 OnSuccess();
567 }
Impressum, Datenschutz