]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/mifare4.c
069c54d4937a23d682cc427936900b7badd32f74
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 int CalculateEncIVCommand(mf4Session
*session
, uint8_t *iv
, bool verbose
) {
21 memcpy(&iv
[0], session
->TI
, 4);
22 memcpy(&iv
[4], &session
->R_Ctr
, 2);
23 memcpy(&iv
[6], &session
->W_Ctr
, 2);
24 memcpy(&iv
[8], &session
->R_Ctr
, 2);
25 memcpy(&iv
[10], &session
->W_Ctr
, 2);
26 memcpy(&iv
[12], &session
->R_Ctr
, 2);
27 memcpy(&iv
[14], &session
->W_Ctr
, 2);
32 int CalculateEncIVResponse(mf4Session
*session
, uint8_t *iv
, bool verbose
) {
33 memcpy(&iv
[0], &session
->R_Ctr
, 2);
34 memcpy(&iv
[2], &session
->W_Ctr
, 2);
35 memcpy(&iv
[4], &session
->R_Ctr
, 2);
36 memcpy(&iv
[6], &session
->W_Ctr
, 2);
37 memcpy(&iv
[8], &session
->R_Ctr
, 2);
38 memcpy(&iv
[10], &session
->W_Ctr
, 2);
39 memcpy(&iv
[12], session
->TI
, 4);
45 int CalculateMAC(mf4Session
*session
, MACType_t mtype
, uint8_t blockNum
, uint8_t blockCount
, uint8_t *data
, int datalen
, uint8_t *mac
, bool verbose
) {
46 if (!session
|| !session
->Authenticated
|| !mac
|| !data
|| !datalen
|| datalen
< 1)
51 uint16_t ctr
= session
->R_Ctr
;
62 uint8_t macdata
[2049] = {data
[0], (ctr
& 0xFF), (ctr
>> 8), 0};
63 int macdatalen
= datalen
;
64 memcpy(&macdata
[3], session
->TI
, 4);
68 memcpy(&macdata
[7], &data
[1], datalen
- 1);
69 macdatalen
= datalen
+ 6;
72 macdata
[7] = blockNum
;
74 macdata
[9] = blockCount
;
75 memcpy(&macdata
[10], &data
[1], datalen
- 1);
76 macdatalen
= datalen
+ 9;
79 memcpy(&macdata
[7], &data
[1], datalen
- 1);
80 macdatalen
= datalen
+ 6;
88 PrintAndLog("MAC data[%d]: %s", macdatalen
, sprint_hex(macdata
, macdatalen
));
90 return aes_cmac8(NULL
, session
->Kmac
, macdata
, mac
, macdatalen
);
93 int MifareAuth4(mf4Session
*session
, uint8_t *keyn
, uint8_t *key
, bool activateField
, bool leaveSignalON
, bool verbose
) {
94 uint8_t data
[257] = {0};
97 uint8_t RndA
[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
98 uint8_t RndB
[17] = {0};
101 session
->Authenticated
= false;
103 uint8_t cmd1
[] = {0x70, keyn
[1], keyn
[0], 0x00};
104 int res
= ExchangeRAW14a(cmd1
, sizeof(cmd1
), activateField
, true, data
, sizeof(data
), &datalen
);
106 PrintAndLog("ERROR exchande raw error: %d", res
);
112 PrintAndLog("<phase1: %s", sprint_hex(data
, datalen
));
115 PrintAndLog("ERROR: card response length: %d", datalen
);
120 if (data
[0] != 0x90) {
121 PrintAndLog("ERROR: card response error: %02x", data
[2]);
126 if (datalen
!= 19) { // code 1b + 16b + crc 2b
127 PrintAndLog("ERROR: card response must be 19 bytes long instead of: %d", datalen
);
132 aes_decode(NULL
, key
, &data
[1], RndB
, 16);
135 PrintAndLog("RndB: %s", sprint_hex(RndB
, 16));
137 uint8_t cmd2
[33] = {0};
140 uint8_t raw
[32] = {0};
141 memmove(raw
, RndA
, 16);
142 memmove(&raw
[16], &RndB
[1], 16);
144 aes_encode(NULL
, key
, raw
, &cmd2
[1], 32);
146 PrintAndLog(">phase2: %s", sprint_hex(cmd2
, 33));
148 res
= ExchangeRAW14a(cmd2
, sizeof(cmd2
), false, true, data
, sizeof(data
), &datalen
);
150 PrintAndLog("ERROR exchande raw error: %d", res
);
156 PrintAndLog("<phase2: %s", sprint_hex(data
, datalen
));
158 aes_decode(NULL
, key
, &data
[1], raw
, 32);
161 PrintAndLog("res: %s", sprint_hex(raw
, 32));
162 PrintAndLog("RndA`: %s", sprint_hex(&raw
[4], 16));
165 if (memcmp(&raw
[4], &RndA
[1], 16)) {
166 PrintAndLog("\nERROR: Authentication FAILED. rnd not equal");
168 PrintAndLog("RndA reader: %s", sprint_hex(&RndA
[1], 16));
169 PrintAndLog("RndA card: %s", sprint_hex(&raw
[4], 16));
176 PrintAndLog(" TI: %s", sprint_hex(raw
, 4));
177 PrintAndLog("pic: %s", sprint_hex(&raw
[20], 6));
178 PrintAndLog("pcd: %s", sprint_hex(&raw
[26], 6));
181 uint8_t kenc
[16] = {0};
182 memcpy(&kenc
[0], &RndA
[11], 5);
183 memcpy(&kenc
[5], &RndB
[11], 5);
184 for(int i
= 0; i
< 5; i
++)
185 kenc
[10 + i
] = RndA
[4 + i
] ^ RndB
[4 + i
];
188 aes_encode(NULL
, key
, kenc
, kenc
, 16);
190 PrintAndLog("kenc: %s", sprint_hex(kenc
, 16));
193 uint8_t kmac
[16] = {0};
194 memcpy(&kmac
[0], &RndA
[7], 5);
195 memcpy(&kmac
[5], &RndB
[7], 5);
196 for(int i
= 0; i
< 5; i
++)
197 kmac
[10 + i
] = RndA
[0 + i
] ^ RndB
[0 + i
];
200 aes_encode(NULL
, key
, kmac
, kmac
, 16);
202 PrintAndLog("kmac: %s", sprint_hex(kmac
, 16));
212 session
->Authenticated
= true;
215 session
->KeyNum
= keyn
[1] + (keyn
[0] << 8);
216 memmove(session
->RndA
, RndA
, 16);
217 memmove(session
->RndB
, RndB
, 16);
218 memmove(session
->Key
, key
, 16);
219 memmove(session
->TI
, raw
, 4);
220 memmove(session
->PICCap2
, &raw
[20], 6);
221 memmove(session
->PCDCap2
, &raw
[26], 6);
222 memmove(session
->Kenc
, kenc
, 16);
223 memmove(session
->Kmac
, kmac
, 16);
226 PrintAndLog("Authentication OK");
231 // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
232 // plus evtl. 8 sectors with 16 blocks each (4k cards)
233 uint8_t mfNumBlocksPerSector(uint8_t sectorNo
) {
240 uint8_t mfFirstBlockOfSector(uint8_t sectorNo
) {
244 return 32 * 4 + (sectorNo
- 32) * 16;
247 uint8_t mfSectorTrailer(uint8_t blockNo
) {
248 if (blockNo
< 32*4) {
249 return (blockNo
| 0x03);
251 return (blockNo
| 0x0f);
255 bool mfIsSectorTrailer(uint8_t blockNo
) {
256 return (blockNo
== mfSectorTrailer(blockNo
));
259 uint8_t mfSectorNum(uint8_t blockNo
) {
260 if (blockNo
< 32 * 4)
263 return 32 + (blockNo
- 32 * 4) / 16;