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