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