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