1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
3 // Copyright (C) 2018 drHatson
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
8 //-----------------------------------------------------------------------------
9 // iso14443-4 mifare commands
10 //-----------------------------------------------------------------------------
18 #include "crypto/libpcrypto.h"
20 AccessConditions_t MFAccessConditions
[] = {
21 {0x00, "read AB; write AB; increment AB; decrement transfer restore AB"},
22 {0x01, "read AB; decrement transfer restore AB"},
24 {0x03, "read B; write B"},
25 {0x04, "read AB; writeB"},
27 {0x06, "read AB; write B; increment B; decrement transfer restore AB"},
31 AccessConditions_t MFAccessConditionsTrailer
[] = {
32 {0x00, "read A by A; read ACCESS by A; read B by A; write B by A"},
33 {0x01, "write A by A; read ACCESS by A write ACCESS by A; read B by A; write B by A"},
34 {0x02, "read ACCESS by A; read B by A"},
35 {0x03, "write A by B; read ACCESS by AB; write ACCESS by B; write B by B"},
36 {0x04, "write A by B; read ACCESS by AB; write B by B"},
37 {0x05, "read ACCESS by AB; write ACCESS by B"},
38 {0x06, "read ACCESS by AB"},
39 {0x07, "read ACCESS by AB"}
42 char *mfGetAccessConditionsDesc(uint8_t blockn
, uint8_t *data
) {
43 static char StaticNone
[] = "none";
45 uint8_t data1
= ((data
[1] >> 4) & 0x0f) >> blockn
;
46 uint8_t data2
= ((data
[2]) & 0x0f) >> blockn
;
47 uint8_t data3
= ((data
[2] >> 4) & 0x0f) >> blockn
;
49 uint8_t cond
= (data1
& 0x01) << 2 | (data2
& 0x01) << 1 | (data3
& 0x01);
52 for (int i
= 0; i
< ARRAYLEN(MFAccessConditionsTrailer
); i
++)
53 if (MFAccessConditionsTrailer
[i
].cond
== cond
) {
54 return MFAccessConditionsTrailer
[i
].description
;
57 for (int i
= 0; i
< ARRAYLEN(MFAccessConditions
); i
++)
58 if (MFAccessConditions
[i
].cond
== cond
) {
59 return MFAccessConditions
[i
].description
;
66 int CalculateEncIVCommand(mf4Session
*session
, uint8_t *iv
, bool verbose
) {
67 memcpy(&iv
[0], session
->TI
, 4);
68 memcpy(&iv
[4], &session
->R_Ctr
, 2);
69 memcpy(&iv
[6], &session
->W_Ctr
, 2);
70 memcpy(&iv
[8], &session
->R_Ctr
, 2);
71 memcpy(&iv
[10], &session
->W_Ctr
, 2);
72 memcpy(&iv
[12], &session
->R_Ctr
, 2);
73 memcpy(&iv
[14], &session
->W_Ctr
, 2);
78 int CalculateEncIVResponse(mf4Session
*session
, uint8_t *iv
, bool verbose
) {
79 memcpy(&iv
[0], &session
->R_Ctr
, 2);
80 memcpy(&iv
[2], &session
->W_Ctr
, 2);
81 memcpy(&iv
[4], &session
->R_Ctr
, 2);
82 memcpy(&iv
[6], &session
->W_Ctr
, 2);
83 memcpy(&iv
[8], &session
->R_Ctr
, 2);
84 memcpy(&iv
[10], &session
->W_Ctr
, 2);
85 memcpy(&iv
[12], session
->TI
, 4);
91 int CalculateMAC(mf4Session
*session
, MACType_t mtype
, uint8_t blockNum
, uint8_t blockCount
, uint8_t *data
, int datalen
, uint8_t *mac
, bool verbose
) {
92 if (!session
|| !session
->Authenticated
|| !mac
|| !data
|| !datalen
|| datalen
< 1)
97 uint16_t ctr
= session
->R_Ctr
;
101 ctr
= session
->W_Ctr
;
108 uint8_t macdata
[2049] = {data
[0], (ctr
& 0xFF), (ctr
>> 8), 0};
109 int macdatalen
= datalen
;
110 memcpy(&macdata
[3], session
->TI
, 4);
114 memcpy(&macdata
[7], &data
[1], datalen
- 1);
115 macdatalen
= datalen
+ 6;
118 macdata
[7] = blockNum
;
120 macdata
[9] = blockCount
;
121 memcpy(&macdata
[10], &data
[1], datalen
- 1);
122 macdatalen
= datalen
+ 9;
125 memcpy(&macdata
[7], &data
[1], datalen
- 1);
126 macdatalen
= datalen
+ 6;
134 PrintAndLog("MAC data[%d]: %s", macdatalen
, sprint_hex(macdata
, macdatalen
));
136 return aes_cmac8(NULL
, session
->Kmac
, macdata
, mac
, macdatalen
);
139 int MifareAuth4(mf4Session
*session
, uint8_t *keyn
, uint8_t *key
, bool activateField
, bool leaveSignalON
, bool verbose
) {
140 uint8_t data
[257] = {0};
143 uint8_t RndA
[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
144 uint8_t RndB
[17] = {0};
147 session
->Authenticated
= false;
149 uint8_t cmd1
[] = {0x70, keyn
[1], keyn
[0], 0x00};
150 int res
= ExchangeRAW14a(cmd1
, sizeof(cmd1
), activateField
, true, data
, sizeof(data
), &datalen
);
152 PrintAndLog("ERROR exchande raw error: %d", res
);
158 PrintAndLog("<phase1: %s", sprint_hex(data
, datalen
));
161 PrintAndLog("ERROR: card response length: %d", datalen
);
166 if (data
[0] != 0x90) {
167 PrintAndLog("ERROR: card response error: %02x", data
[2]);
172 if (datalen
!= 19) { // code 1b + 16b + crc 2b
173 PrintAndLog("ERROR: card response must be 19 bytes long instead of: %d", datalen
);
178 aes_decode(NULL
, key
, &data
[1], RndB
, 16);
181 PrintAndLog("RndB: %s", sprint_hex(RndB
, 16));
183 uint8_t cmd2
[33] = {0};
186 uint8_t raw
[32] = {0};
187 memmove(raw
, RndA
, 16);
188 memmove(&raw
[16], &RndB
[1], 16);
190 aes_encode(NULL
, key
, raw
, &cmd2
[1], 32);
192 PrintAndLog(">phase2: %s", sprint_hex(cmd2
, 33));
194 res
= ExchangeRAW14a(cmd2
, sizeof(cmd2
), false, true, data
, sizeof(data
), &datalen
);
196 PrintAndLog("ERROR exchande raw error: %d", res
);
202 PrintAndLog("<phase2: %s", sprint_hex(data
, datalen
));
204 aes_decode(NULL
, key
, &data
[1], raw
, 32);
207 PrintAndLog("res: %s", sprint_hex(raw
, 32));
208 PrintAndLog("RndA`: %s", sprint_hex(&raw
[4], 16));
211 if (memcmp(&raw
[4], &RndA
[1], 16)) {
212 PrintAndLog("\nERROR: Authentication FAILED. rnd not equal");
214 PrintAndLog("RndA reader: %s", sprint_hex(&RndA
[1], 16));
215 PrintAndLog("RndA card: %s", sprint_hex(&raw
[4], 16));
222 PrintAndLog(" TI: %s", sprint_hex(raw
, 4));
223 PrintAndLog("pic: %s", sprint_hex(&raw
[20], 6));
224 PrintAndLog("pcd: %s", sprint_hex(&raw
[26], 6));
227 uint8_t kenc
[16] = {0};
228 memcpy(&kenc
[0], &RndA
[11], 5);
229 memcpy(&kenc
[5], &RndB
[11], 5);
230 for(int i
= 0; i
< 5; i
++)
231 kenc
[10 + i
] = RndA
[4 + i
] ^ RndB
[4 + i
];
234 aes_encode(NULL
, key
, kenc
, kenc
, 16);
236 PrintAndLog("kenc: %s", sprint_hex(kenc
, 16));
239 uint8_t kmac
[16] = {0};
240 memcpy(&kmac
[0], &RndA
[7], 5);
241 memcpy(&kmac
[5], &RndB
[7], 5);
242 for(int i
= 0; i
< 5; i
++)
243 kmac
[10 + i
] = RndA
[0 + i
] ^ RndB
[0 + i
];
246 aes_encode(NULL
, key
, kmac
, kmac
, 16);
248 PrintAndLog("kmac: %s", sprint_hex(kmac
, 16));
258 session
->Authenticated
= true;
261 session
->KeyNum
= keyn
[1] + (keyn
[0] << 8);
262 memmove(session
->RndA
, RndA
, 16);
263 memmove(session
->RndB
, RndB
, 16);
264 memmove(session
->Key
, key
, 16);
265 memmove(session
->TI
, raw
, 4);
266 memmove(session
->PICCap2
, &raw
[20], 6);
267 memmove(session
->PCDCap2
, &raw
[26], 6);
268 memmove(session
->Kenc
, kenc
, 16);
269 memmove(session
->Kmac
, kmac
, 16);
272 PrintAndLog("Authentication OK");
277 // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
278 // plus evtl. 8 sectors with 16 blocks each (4k cards)
279 uint8_t mfNumBlocksPerSector(uint8_t sectorNo
) {
286 uint8_t mfFirstBlockOfSector(uint8_t sectorNo
) {
290 return 32 * 4 + (sectorNo
- 32) * 16;
293 uint8_t mfSectorTrailer(uint8_t blockNo
) {
294 if (blockNo
< 32*4) {
295 return (blockNo
| 0x03);
297 return (blockNo
| 0x0f);
301 bool mfIsSectorTrailer(uint8_t blockNo
) {
302 return (blockNo
== mfSectorTrailer(blockNo
));
305 uint8_t mfSectorNum(uint8_t blockNo
) {
306 if (blockNo
< 32 * 4)
309 return 32 + (blockNo
- 32 * 4) / 16;