]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/mifaredesfire.c
FIX: a shot at fixing the "_" underscore problem in fileutils.c. This one uses _ifde...
[proxmark3-svn] / armsrc / mifaredesfire.c
1 #include "mifaredesfire.h"
2 #include "des.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 // Make sure it is off.
23 // FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
24 // SpinDelay(300);
25
26 byte_t cardbuf[USB_CMD_DATA_SIZE];
27 memset(cardbuf,0,sizeof(cardbuf));
28 iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
29
30 iso14a_set_tracing(TRUE);
31 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
32
33 int len = iso14443a_select_card(NULL,card,NULL);
34
35 if (!len) {
36 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
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[RECEIVE_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 == 0) {
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 = get_bigbufptr_recvrespbuf();
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 (algo == 1) {
221
222 uint8_t keybytes[8];
223 uint8_t RndA[8] = {0x00};
224 uint8_t RndB[8] = {0x00};
225
226 if (datain[1] == 0xff){
227 memcpy(keybytes,null_key_data8,8);
228 } else{
229 memcpy(keybytes, datain+1, datalen);
230 }
231
232 struct desfire_key defaultkey = {0};
233 desfirekey_t key = &defaultkey;
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 >= 1) {
241 DbpString("Authentication failed. Card timeout.");
242 }
243 OnError();
244 return;
245 }
246
247 if ( resp[2] == 0xaf ){
248 } else {
249 DbpString("Authetication failed. Invalid key number.");
250 OnError();
251 return;
252 }
253
254 memcpy( encRndB, resp+3, 8);
255
256 des_dec(&decRndB, &encRndB, key->data);
257 memcpy(RndB, decRndB, 8);
258 rol(decRndB,8);
259
260 // This should be random
261 uint8_t decRndA[8] = {0x00};
262 memcpy(RndA, decRndA, 8);
263 uint8_t encRndA[8] = {0x00};
264
265 des_dec(&encRndA, &decRndA, key->data);
266
267 memcpy(both, encRndA, 8);
268
269 for (int x = 0; x < 8; x++) {
270 decRndB[x] = decRndB[x] ^ encRndA[x];
271
272 }
273
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 >= 1) {
284 DbpString("Authentication failed. Card timeout.");
285 }
286 OnError();
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 des_dec(&encRndA, &encRndA, key->data);
299 rol(decRndA,8);
300 for (int x = 0; x < 8; x++) {
301 if (decRndA[x] != encRndA[x]) {
302 DbpString("Authetication failed. Cannot varify PICC.");
303 OnError();
304 return;
305 }
306 }
307
308 //Change the selected key to a new value.
309 /*
310
311 cmd[0] = CHANGE_KEY;
312 cmd[1] = keyno;
313
314 uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
315
316 uint8_t first, second;
317 uint8_t buff1[8] = {0x00};
318 uint8_t buff2[8] = {0x00};
319 uint8_t buff3[8] = {0x00};
320
321 memcpy(buff1,newKey, 8);
322 memcpy(buff2,newKey + 8, 8);
323
324 ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
325 memcpy(buff3, &first, 1);
326 memcpy(buff3 + 1, &second, 1);
327
328 des_dec(&buff1, &buff1, skey->data);
329 memcpy(cmd+2,buff1,8);
330
331 for (int x = 0; x < 8; x++) {
332 buff2[x] = buff2[x] ^ buff1[x];
333 }
334 des_dec(&buff2, &buff2, skey->data);
335 memcpy(cmd+10,buff2,8);
336
337 for (int x = 0; x < 8; x++) {
338 buff3[x] = buff3[x] ^ buff2[x];
339 }
340 des_dec(&buff3, &buff3, skey->data);
341 memcpy(cmd+18,buff3,8);
342
343 // The command always times out on the first attempt, this will retry until a response
344 // is recieved.
345 len = 0;
346 while(!len) {
347 len = DesfireAPDU(cmd,26,resp);
348 }
349 */
350
351 OnSuccess();
352 cmd_send(CMD_ACK,1,0,0,skey->data,8);
353
354 } else {
355 DbpString("Authetication failed.");
356 OnError();
357 return;
358 }
359
360 }
361 }
362 break;
363 case 2:
364 //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
365 break;
366 case 3:{
367
368 //defaultkey
369 uint8_t keybytes[16];
370 if (datain[1] == 0xff){
371 memcpy(keybytes,PICC_MASTER_KEY16,16);
372 } else{
373 memcpy(keybytes, datain+1, datalen);
374 }
375
376 struct desfire_key defaultkey = {0};
377 desfirekey_t key = &defaultkey;
378 Desfire_aes_key_new( keybytes, key);
379
380 AesCtx ctx;
381 if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
382 if( MF_DBGLEVEL >= 4) {
383 Dbprintf("AES context failed to init");
384 }
385 OnError();
386 return;
387 }
388
389 cmd[0] = AUTHENTICATE_AES;
390 cmd[1] = 0x00; //keynumber
391 len = DesfireAPDU(cmd, 2, resp);
392 if ( !len ) {
393 if (MF_DBGLEVEL >= 1) {
394 DbpString("Authentication failed. Card timeout.");
395 }
396 OnError();
397 return;
398 }
399
400 memcpy( encRndB, resp+3, 16);
401
402 // dekryptera tagnonce.
403 AesDecrypt(&ctx, encRndB, decRndB, 16);
404 rol(decRndB,16);
405 memcpy(both, nonce,16);
406 memcpy(both+16, decRndB ,16 );
407 AesEncrypt(&ctx, both, encBoth, 32 );
408
409 cmd[0] = ADDITIONAL_FRAME;
410 memcpy(cmd+1, encBoth, 32 );
411
412 len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
413 if ( !len ) {
414 if (MF_DBGLEVEL >= 1) {
415 DbpString("Authentication failed. Card timeout.");
416 }
417 OnError();
418 return;
419 }
420
421 if ( resp[2] == 0x00 ){
422 // Create AES Session key
423 struct desfire_key sessionKey = {0};
424 desfirekey_t skey = &sessionKey;
425 Desfire_session_key_new( nonce, decRndB , key, skey );
426 print_result("SESSION : ", skey->data, 16);
427 } else {
428 DbpString("Authetication failed.");
429 OnError();
430 return;
431 }
432
433 break;
434 }
435 }
436
437 OnSuccess();
438 cmd_send(CMD_ACK,1,len,0,resp,len);
439 }
440
441 // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
442 // cmd = cmd bytes to send
443 // cmd_len = length of cmd
444 // dataout = pointer to response data array
445 int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
446
447 size_t len = 0;
448 size_t wrappedLen = 0;
449 uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
450
451 uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
452 uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
453
454 wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
455
456 if (MF_DBGLEVEL >= 4) {
457 print_result("WCMD <--: ", wCmd, wrappedLen);
458 }
459 ReaderTransmit( wCmd, wrappedLen, NULL);
460
461 len = ReaderReceive(resp, resp_par);
462
463 if( len == 0x00 ){
464 if (MF_DBGLEVEL >= 4) {
465 Dbprintf("fukked");
466 }
467 return FALSE; //DATA LINK ERROR
468 }
469 // if we received an I- or R(ACK)-Block with a block number equal to the
470 // current block number, toggle the current block number
471 else if (len >= 4 // PCB+CID+CRC = 4 bytes
472 && ((resp[0] & 0xC0) == 0 // I-Block
473 || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
474 && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
475 {
476 pcb_blocknum ^= 1; //toggle next block
477 }
478
479 memcpy(dataout, resp, len);
480 return len;
481 }
482
483 // CreateAPDU
484 size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
485
486 size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
487
488 uint8_t cmd[cmdlen];
489 memset(cmd, 0, cmdlen);
490
491 cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
492 cmd[0] |= pcb_blocknum; // OR the block number into the PCB
493 cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
494
495 memcpy(cmd+2, datain, len);
496 AppendCrc14443a(cmd, len+2);
497
498 memcpy(dataout, cmd, cmdlen);
499
500 return cmdlen;
501 }
502
503 // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
504 // crc_update(&desfire_crc32, addr, addr_sz);
505 // crc_update(&desfire_crc32, byte, 8);
506 // uint32_t crc = crc_finish(&desfire_crc32);
507
508 void OnSuccess(){
509 pcb_blocknum = 0;
510 ReaderTransmit(deselect_cmd, 3 , NULL);
511 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
512 LEDsoff();
513 }
514
515 void OnError(){
516 pcb_blocknum = 0;
517 ReaderTransmit(deselect_cmd, 3 , NULL);
518 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
519 cmd_send(CMD_ACK,0,0,0,0,0);
520 LEDsoff();
521 }
Impressum, Datenschutz