nfc test on MQX4.1
[nfc-test.git] / mifare.c
blob6e589a85bf55f5d337e221abd1ad0a99075ba946
2 #include "common.h"
3 #include "picc.h"
4 #include "mifare.h"
5 #include "iso14443_typeA.h"
7 int mifare_select(struct picc_device *picc)
9 int ret;
10 uint8_t i;
11 uint8_t tempUIDLength;
12 uint8_t tempUID[5];
13 uint8_t level = 0;
15 ret = typeA_request(picc, PICC_WUPA);
16 if(ret == -ERROR_NOTAG) {
17 ret = typeA_request(picc, PICC_WUPA);
19 if(ret != -ERROR_NOTAG) {
20 tempUIDLength = picc->sn_len;
21 i = 0;
22 while(tempUIDLength) {
23 if(tempUIDLength == 4) {
24 memcpy(tempUID, picc->sn + i, 4);
25 tempUIDLength -= 4;
27 else { /* Double and triple size UIDs */
28 tempUID[0] = 0x88;
29 memcpy(tempUID + 1, picc->sn + i, 3);
30 tempUIDLength -= 3;
31 i += 3;
33 ret = typeA_cascade_select(picc, selectCmd[level], tempUID);
34 level++;
37 if(!ret) {
38 picc->authen_need = 0x01;
39 picc->states = PICC_SELECTED;
42 return(ret);
45 static int mifare_authen_analyze(struct picc_device *picc, uint8_t *MFAuthKey)
47 int ret = 0;
48 struct pn51x_request *req = picc->request;
50 req->buf[0] = picc->key_type;
51 req->buf[1] = picc->block;
52 memcpy(req->buf + 2, MFAuthKey, 6);
53 if(picc->sn_len == 7)
54 memcpy(req->buf+8, &picc->sn[3], 4);
55 else
56 memcpy(req->buf+8, picc->sn, 4);
58 req->length = 12;
59 req->bit_frame = 0x00;
60 req->command = CMD_MFAUTHENT;
61 req->direction = TRANSMIT;
62 req->time_out = 3000;
63 req->timer_start_now = 1;
64 picc_wait_for_req(req);
66 if(!req->error_code || req->error_code == -ERROR_NOTAG) {
67 if(pn51x_reg_read(Status2Reg) & 0x08) // pn512 P31
68 ret = 0;
69 else
70 ret = -PICC_ERRORCODE_MUTE;
72 else
73 ret = -PICC_ERRORCODE_MUTE;
75 return ret;
78 static int mifare_check_read_write_len(struct picc_device *picc, uint8_t BlockNum, uint8_t TempLe)
80 int ret = 0;
82 if((picc->SAK & 0xDF) == SAK_MIFARE_4K) {
83 if(BlockNum >= 0x80) { // sector 32 ~ sector 39, has 16 blocks in each sector
84 if((TempLe > 0xF0) || (TempLe & 0x0F)) {
85 ret = 0x01;
88 else { // sector 0 ~ sector 31, has 4 blocks in each sector
89 if((TempLe > 0x30) || (TempLe & 0x0F)) {
90 ret = 0x01;
94 else if(((picc->SAK & 0xDF) == SAK_MIFARE_1K) || ((picc->SAK & 0xDF) == SAK_MIFARE_MINI)) {
95 if((TempLe > 0x30) || (TempLe & 0x0F)) {
96 ret = 0x01;
99 else {
100 if((TempLe < 4) || (TempLe > 0x10)) {
101 ret = 0x01;
105 return(ret);
108 static int mifare_authen(struct picc_device *picc)
110 int ret = 0;
112 if(((picc->key_valid & 0x01) && (picc->key_No == 0x00))
113 || ((picc->key_valid & 0x02) && (picc->key_No == 0x01))) {
114 ret = mifare_authen_analyze(picc, (uint8_t *)picc->work_key); /* why reauthen for keyno 0 key valid = 1 ? */
115 if(!ret) {
116 picc->authen_need = 0x00;
118 else {
119 picc->authen_need = 0x01;
122 else {
123 ret = 0;
124 picc->authen_need = 0x01;
127 return(ret);
130 static int mifare_block_check(struct picc_device *picc, uint8_t srcBlock, uint8_t desBlock, BOOL multBlockMode)
132 uint8_t i;
133 uint8_t j;
134 int ret = 0;
136 if(multBlockMode == TRUE) {
137 //For safety reason, the Multiple Block Mode is used for accessing Data Blocks only
138 if(srcBlock >= 0x80) {
139 if((srcBlock & 0x0F) == 0x0F) { /* 16 block ,0xXF last block is control block */
140 ret = 0x01;
143 else {
144 if((srcBlock & 0x03) == 0x03) {
145 ret = 0x01;
150 if(picc->block >= 0x80) { //For Mifare 4K large block
151 i=(uint8_t)(srcBlock / 16); // calculate the source sector number
152 j=(uint8_t)(desBlock / 16); // calculate the target sector number
153 if((i != (uint8_t)(picc->block / 16)) || (j != (uint8_t)(picc->block / 16))) {
154 ret = 1; // skip
157 else {
158 i=(uint8_t)(srcBlock / 4); // calculate the source sector number
159 j=(uint8_t)(desBlock / 4); // calculate the target sector number
160 if((i != (uint8_t)(picc->block / 4)) || (j != (uint8_t)(picc->block / 4))) {
161 ret = 1; // skip
165 return(ret);
169 static int mifare_block_read(struct picc_device *picc, uint8_t addr, uint8_t *blockData)
171 struct pn51x_request *req = picc->request;
172 int ret;
174 req->buf[0] = PICC_MF_READ;
175 req->buf[1] = addr; /* block number ? */
177 req->length = 2;
178 req->bit_frame = 0x00;
179 req->command = CMD_TRANSCEIVE;
180 req->direction = TRANSCEIVE;
181 req->time_out = 100;
182 req->timer_start_auto = 1;
183 picc_wait_for_req(req);
185 memcpy(blockData, req->buf, req->actual);
187 if(req->error_code)
188 ret = -PICC_ERRORCODE_XFR_PARITY_ERROR;
189 else {
190 if (req->actual != 16)
191 ret = -PICC_ERRORCODE_HW_ERROR;
192 else
193 ret = 0;
196 return ret;
199 static int mifare_block_write(struct picc_device *picc, uint8_t opcode, uint8_t addr, uint8_t *blockData)
201 int ret = 0;
202 uint8_t tempBuf[5];
203 struct pn51x_request *req = picc->request;
205 req->buf[0] = opcode;
206 req->buf[1] = addr;
207 req->length = 2;
209 if(opcode == PICC_MF_WRITE_4_BYTES) {
210 memcpy(req->buf + 2, blockData, 4);
211 req->length = 6;
214 req->bit_frame = 0x00;
215 req->command = CMD_TRANSCEIVE;
216 req->direction = TRANSCEIVE;
217 req->time_out = 600;
218 req->timer_start_auto = 1;
219 picc_wait_for_req(req);
221 memcpy(tempBuf, req->buf, req->actual);
223 ret = req->error_code;
224 if(ret != -ERROR_NOTAG) {
225 if(req->bit_numbers != 4) {
226 ret = -PICC_ERRORCODE_MUTE;
228 else {
229 if((tempBuf[0] & 0x0f) == 0x0A) { /* recv 0x0A is successed */
230 ret = 0;
231 if(opcode == PICC_MF_WRITE_4_BYTES) {
232 goto err;
235 else {
236 ret = -PICC_ERRORCODE_MUTE;
240 else {
241 ret = -PICC_ERRORCODE_MUTE;
244 if(!ret) { /* write the true data */
245 memcpy(req->buf, blockData, 16);
246 req->length = 16;
248 req->bit_frame = 0x00;
249 req->command = CMD_TRANSCEIVE;
250 req->direction = TRANSCEIVE;
251 req->time_out = 600;
253 picc_wait_for_req(req);
255 memcpy(tempBuf, req->buf, req->actual);
257 if(req->error_code == -ERROR_NOTAG) {
258 // timeout occured
259 ret = -PICC_ERRORCODE_MUTE;
261 else {
262 if(req->bit_numbers != 4) {
263 ret = -PICC_ERRORCODE_MUTE;
265 else {
266 // 4 bit received
267 if((tempBuf[0] & 0x0f) == 0x0A) {
268 ret = 0;
270 else {
271 ret = -PICC_ERRORCODE_MUTE;
277 err:
278 return(ret);
281 static int mifare_inc_dec(struct picc_device *picc, uint8_t opcode, uint8_t addr, uint8_t *value)
283 int ret;
284 uint8_t tempBuf[5];
285 struct pn51x_request *req = picc->request;
287 req->buf[0] = opcode;
288 req->buf[1] = addr;
289 req->length = 2;
290 req->bit_frame = 0x00;
291 req->command = CMD_TRANSCEIVE;
292 req->direction = TRANSCEIVE;
293 if(opcode == PICC_MF_TRANSFER)
294 req->time_out = 120;
295 else
296 req->time_out = 15;
298 picc_wait_for_req(req);
300 memcpy(tempBuf, req->buf, req->actual);
302 ret = req->error_code;
304 if(ret != -ERROR_NOTAG) {
305 if(req->bit_numbers != 4) {
306 ret = -PICC_ERRORCODE_MUTE;
308 else {
309 if((tempBuf[0] & 0x0f) == 0x0A) {
310 ret = 0;
312 else {
313 ret = -PICC_ERRORCODE_MUTE;
317 else {
318 ret = -PICC_ERRORCODE_HW_ERROR;
321 if(!ret && opcode != PICC_MF_TRANSFER) {
322 req->buf[0] = value[3];
323 req->buf[1] = value[2];
324 req->buf[2] = value[1];
325 req->buf[3] = value[0];
326 req->length = 4;
327 req->bit_frame = 0x00;
328 req->command = CMD_TRANSCEIVE;
329 req->direction = TRANSCEIVE;
330 req->time_out = 15;
332 picc_wait_for_req(req);
334 memcpy(tempBuf, req->buf, req->actual);
336 if(req->error_code == -ERROR_NOTAG) {
337 ret = 0;
339 else {
340 ret = -PICC_ERRORCODE_MUTE;
344 return(ret);
347 int mifare_pcsc_command(struct picc_device *picc, uint8_t *senBuf, uint32_t senLen, uint8_t *recBuf, uint32_t *recLen)
349 uint32_t i;
350 int ret = 0;
351 uint8_t mifareBlock;
352 uint8_t tempLe;
353 BOOL multBlockMode;
354 uint8_t mifareOpcode;
355 uint8_t *pResAddr;
357 /******* Load Authentication Keys ************/
358 // accroding to pcsc part3, Requirements for PC-Connected Interface Devices
359 if((senLen == 11) && (senBuf[1] == 0x82) && (senBuf[4] == 0x06)) {
360 if((senBuf[2] == 0x00) && (senBuf[3] <= 0x01)) {
361 for(i = 0; i < 6; i++) {
362 picc->pcd->mifare_key[senBuf[3]][i] = senBuf[5 + i];
365 recBuf[0] = 0x90;
366 recBuf[1] = 0x00;
367 *recLen = 0x02;
368 ret = 0;
370 // incorrect parameters
371 else {
372 ret = SLOT_ERROR;
376 /************ Authentication for MIFARE 1K/4K ************/
377 // Check Authentication V2.0X
378 // FF 86 00 00 05 ADB
379 else if((senLen == 10) && (senBuf[1] == 0x86) && (senBuf[2] == 0x00) && (senBuf[3] == 0x00) && (senBuf[4] == 0x05)) {
380 if(picc->states != PICC_SELECTED) {
381 ret = mifare_select(picc);
383 if(((senBuf[8] == PICC_MF_KEY_A)||(senBuf[8] == PICC_MF_KEY_B)) && (senBuf[9] <= 0x01)) {
384 picc->block = senBuf[7];
385 picc->key_type = senBuf[8];
386 picc->key_No = senBuf[9];
387 ret = mifare_authen_analyze(picc, picc->pcd->mifare_key[picc->key_No]);
388 if(!ret) {
389 if(picc->key_No == 0x00) {
390 picc->key_valid |= 0x01;
392 else {
393 picc->key_valid |= 0x02;
395 for(i = 0; i < 6; i++) {
396 picc->work_key[i] = picc->pcd->mifare_key[picc->key_No][i];
399 recBuf[0] = 0x90;
400 recBuf[1] = 0x00;
401 *recLen = 0x02;
403 else {
404 if(picc->key_No == 0x00) {
405 picc->key_valid &= 0xFE;
407 else {
408 picc->key_valid &= 0xFD;
412 else {
413 ret = SLOT_ERROR;
416 // Check Authentication V1.0X
417 // FF 88 00 BLOCK_NO KEY_TYPE KEY_NO
418 else if((senLen == 0x06) && (senBuf[1] == 0x88) && (senBuf[2] == 0x00))
420 if(picc->states != PICC_SELECTED) {
421 ret = mifare_select(picc);
423 if(((senBuf[4] == PICC_MF_KEY_A) || (senBuf[4] == PICC_MF_KEY_B)) && (senBuf[5] <= 0x01)) {
424 picc->block = senBuf[3];
425 picc->key_type = senBuf[4];
426 picc->key_No = senBuf[5];
427 ret = mifare_authen_analyze(picc, picc->pcd->mifare_key[picc->key_No]);
428 if(!ret) {
429 if(picc->key_No == 0x00) { /* authen successed */
430 picc->key_valid |= 0x01;
432 else {
433 picc->key_valid |= 0x02;
435 for(i = 0; i < 6; i++) {
436 picc->work_key[i] = picc->pcd->mifare_key[picc->key_No][i];
439 recBuf[0] = 0x90;
440 recBuf[1] = 0x00;
441 *recLen = 0x02;
443 else {
444 if(picc->key_No == 0x00) { /* authen failed */
445 picc->key_valid &= 0xFE;
447 else {
448 picc->key_valid &= 0xFD;
452 else {
453 ret = SLOT_ERROR;
456 // check Binary Read
457 // FF B0 00 BLOCK_NO LE
458 else if((senLen == 5) && (senBuf[1] == 0xB0) && (senBuf[2] == 0x00)) {
459 ret = mifare_check_read_write_len(picc, senBuf[3], senBuf[4]);
460 if(!ret) {
461 if((picc->authen_need == 0x01) && (picc->SAK != SAK_MIFARE_ULTRALIGHT)) {
462 mifare_authen(picc);
464 mifareBlock = senBuf[3];
465 tempLe = senBuf[4];
466 pResAddr = recBuf;
467 *recLen = tempLe;
468 if(tempLe > 0x10) {
469 multBlockMode = TRUE;
471 else {
472 multBlockMode = FALSE;
475 do {
476 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
477 ret = mifare_block_check(picc, mifareBlock, mifareBlock, multBlockMode);
478 tempLe -= 0x10;
480 else {
481 ret = 0;
484 if(!ret) {
485 ret = mifare_block_read(picc, mifareBlock, pResAddr);
486 pResAddr += 0x10;
488 if(ret) {
489 break;
491 mifareBlock++;
492 if(picc->SAK == SAK_MIFARE_ULTRALIGHT) {
493 break;
495 }while(tempLe);
497 if(!ret) {
498 recBuf[(*recLen)++] = 0x90;
499 recBuf[(*recLen)++] = 0x00;
503 // check Binary Write
504 // FF D6 00 BLOCK_NO LE
505 else if((senBuf[1] == 0xD6) && (senBuf[2] == 0x00)) {
506 ret = mifare_check_read_write_len(picc, senBuf[3], senBuf[4]);
507 if(!ret) {
508 if((picc->authen_need == 0x01) && (picc->SAK != SAK_MIFARE_ULTRALIGHT)) {
509 mifare_authen(picc);
511 mifareBlock = senBuf[3];
512 tempLe = senBuf[4];
513 pResAddr = senBuf+5;
514 *recLen = tempLe;
515 if(tempLe > 0x10) {
516 multBlockMode = TRUE;
518 else {
519 multBlockMode = FALSE;
522 do {
523 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
524 ret = mifare_block_check(picc, mifareBlock, mifareBlock, multBlockMode);
525 tempLe -= 0x10;
526 mifareOpcode = PICC_MF_WRITE_16_BYTES;
528 else {
529 ret = 0;
530 tempLe -= 0x04;
531 mifareOpcode = PICC_MF_WRITE_4_BYTES;
533 if(!ret) {
534 ret = mifare_block_write(picc, mifareOpcode, mifareBlock, pResAddr);
535 if(mifareOpcode == PICC_MF_WRITE_16_BYTES) {
536 pResAddr += 0x10;
538 else {
539 pResAddr += 0x04;
542 if(ret) {
543 break;
545 mifareBlock++;
546 }while(tempLe);
548 if(!ret) {
549 recBuf[0] = 0x90;
550 recBuf[1] = 0x00;
551 *recLen = 0x02;
553 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
554 if((mifareBlock >= 0x80) && ((mifareBlock % 16) == 0x00)) {
555 picc->pcd->piccPoll = TRUE;
557 else if((mifareBlock % 4) == 0x00) {
558 picc->pcd->piccPoll = TRUE;
564 // check Value Block Read
565 // FF B1 00 BLOCK_NO 04
566 else if((senLen == 5) && (senBuf[1] == 0xB1) && (senBuf[2] == 0x00) && (senBuf[4] == 0x04)) {
567 if((picc->authen_need == 0x01) && (picc->SAK != SAK_MIFARE_ULTRALIGHT)) {
568 mifare_authen(picc);
570 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
571 ret = mifare_block_check(picc, senBuf[3], senBuf[3], FALSE);
573 else {
574 ret = SLOT_ERROR;
576 if( !ret) {
577 ret = mifare_block_read(picc, senBuf[3], recBuf);
579 if(!ret) {
580 // check the Value Block Format
581 for(i = 0; i < 4; i++) {
582 if((recBuf[i] != recBuf[8 + i])||((recBuf[i] ^ recBuf[4 + i]) != 0xff)) {
583 ret = 1;
587 if(!ret) {
588 for(i = 0; i < 4; i++) {
589 recBuf[i] = recBuf[11 - i];
592 recBuf[4] = 0x90;
593 recBuf[5] = 0x00;
594 *recLen = 6;
599 // check Value Block Operation
600 // FF D7 00 BLOCK_NO 05 VB_OP VB_VALUE
601 else if((senLen == 10) && (senBuf[1] == 0xD7) && (senBuf[2] == 0x00) && (senBuf[4] == 0x05) && (senBuf[5] < 0x03)) {
602 if((picc->authen_need == 0x01) && (picc->SAK != SAK_MIFARE_ULTRALIGHT)) {
603 mifare_authen(picc);
605 mifareBlock = senBuf[3];
606 // step 1. Store Value Operation
607 // STORE Value Operation
608 if(senBuf[5] == 0x00) {
609 mifareOpcode = PICC_MF_WRITE_16_BYTES;
610 senBuf[13] = senBuf[9];
611 senBuf[14] = senBuf[8];
612 senBuf[15] = senBuf[7];
613 senBuf[16] = senBuf[6];
615 senBuf[5] = senBuf[13];
616 senBuf[6] = senBuf[14];
617 senBuf[7] = senBuf[15];
618 senBuf[8] = senBuf[16];
620 senBuf[9] = ~senBuf[5];
621 senBuf[10] = ~senBuf[6];
622 senBuf[11] = ~senBuf[7];
623 senBuf[12] = ~senBuf[8];
625 senBuf[17] = mifareBlock;
626 senBuf[18] = ~mifareBlock;
627 senBuf[19] = mifareBlock;
628 senBuf[20] = ~mifareBlock;
631 // Increment Operation
632 else if(senBuf[5]==0x01) {
633 mifareOpcode = PICC_MF_INCREMENT;
635 // Decrement Operation
636 else {
637 mifareOpcode = PICC_MF_DECREMENT;
639 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
640 ret = mifare_block_check(picc, mifareBlock, mifareBlock, FALSE);
642 else {
643 ret = SLOT_ERROR;
646 if(!ret) {
647 if(mifareOpcode == PICC_MF_WRITE_16_BYTES) {
648 ret = mifare_block_write(picc, mifareOpcode, mifareBlock, senBuf+5);
650 else {
651 ret = mifare_inc_dec(picc, mifareOpcode, mifareBlock, senBuf+6);
655 if(!ret) {
656 // Step 2. Transfer Operation
657 if((mifareOpcode == PICC_MF_INCREMENT) || (mifareOpcode == PICC_MF_DECREMENT)) {
658 ret = mifare_inc_dec(picc, PICC_MF_TRANSFER, mifareBlock, senBuf+6);
660 if(!ret) {
661 recBuf[0] = 0x90;
662 recBuf[1] = 0x00;
663 *recLen = 2;
667 // check Restore Value Block Operation
668 // FF D7 00 srcBlock 02 03 desBlock
669 else if((senLen == 7) && (senBuf[1] == 0xD7) && (senBuf[2] == 0x00)
670 && (senBuf[4] == 0x02) && (senBuf[5] == 0x03)) {
671 if((picc->authen_need == 0x01) && (picc->SAK != SAK_MIFARE_ULTRALIGHT)) {
672 mifare_authen(picc);
674 mifareBlock = senBuf[6];
675 // step 1. Restore Value Operation
676 // Restore Value Operation
678 if(picc->SAK != SAK_MIFARE_ULTRALIGHT) {
679 ret = mifare_block_check(picc, senBuf[3], senBuf[6], FALSE);
681 else {
682 ret = SLOT_ERROR;
685 if( !ret) {
686 ret = mifare_inc_dec(picc, PICC_MF_RESTORE, senBuf[3], senBuf+6);
689 if(!ret) {
690 // Step 2. Transfer Operation
691 ret = mifare_inc_dec(picc, PICC_MF_TRANSFER, mifareBlock, senBuf+6);
692 if(!ret) {
693 recBuf[0] = 0x90;
694 recBuf[1] = 0x00;
695 *recLen = 2;
699 else {
700 ret = -PICC_ERRORCODE_CMD_ABORTED;
703 if(!ret) {
704 picc->pcd->poll_interval = 1000; // 1000ms, start another poll
705 picc->pcd->piccPoll = FALSE;
707 else if(ret == -PICC_ERRORCODE_CMD_ABORTED) {
708 recBuf[0] = 0x6A;
709 recBuf[1] = 0x81;
710 *recLen = 0x02;
711 ret = 0;
712 picc->pcd->piccPoll = TRUE;
714 else {
715 recBuf[0] = 0x63;
716 recBuf[1] = 0x00;
717 *recLen = 0x02;
718 ret = 0;
719 picc->pcd->piccPoll = TRUE;
722 return(ret);
725 void mifare_type_coding(struct picc_device *picc)
727 picc->type = PICC_MIFARE;
728 switch(picc->SAK)
730 case 0x00:
731 picc->name = "mifare ultralight (C) CL2";
732 break;
733 case 0x09:
734 picc->name = "mifare mini(0.3k)";
735 break;
736 case 0x08:
737 picc->name = "mifare classic 1K";
738 break;
739 case 0x18:
740 picc->name = "mifare classic 4K";
741 break;
742 case 0x20:
743 picc->name = "mifare desfire";
744 break;
745 default:
746 picc->name = "unkonw tag";
747 break;