]> git.zerfleddert.de Git - proxmark3-svn/blame - client/mifare4.c
fix warning under linux (#709)
[proxmark3-svn] / client / mifare4.c
CommitLineData
ae3340a0
OM
1//-----------------------------------------------------------------------------
2// Copyright (C) 2018 Merlok
4b5d696c 3// Copyright (C) 2018 drHatson
ae3340a0
OM
4//
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
7// the license.
8//-----------------------------------------------------------------------------
9// iso14443-4 mifare commands
10//-----------------------------------------------------------------------------
11
12#include "mifare4.h"
13#include <ctype.h>
14#include <string.h>
15#include "cmdhf14a.h"
16#include "util.h"
17#include "ui.h"
18#include "polarssl/libpcrypto.h"
19
4b5d696c 20int 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);
28
29 return 0;
30}
31
32int 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);
40
41 return 0;
42}
43
44
45int 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)
c8a0f550
OM
47 return 1;
48
49 memset(mac, 0x00, 8);
4b5d696c 50
51 uint16_t ctr = session->R_Ctr;
52 switch(mtype) {
53 case mtypWriteCmd:
54 case mtypWriteResp:
55 ctr = session->W_Ctr;
56 break;
57 case mtypReadCmd:
58 case mtypReadResp:
59 break;
60 }
61
62 uint8_t macdata[2049] = {data[0], (ctr & 0xFF), (ctr >> 8), 0};
63 int macdatalen = datalen;
64 memcpy(&macdata[3], session->TI, 4);
65
66 switch(mtype) {
67 case mtypReadCmd:
68 memcpy(&macdata[7], &data[1], datalen - 1);
69 macdatalen = datalen + 6;
70 break;
71 case mtypReadResp:
72 macdata[7] = blockNum;
73 macdata[8] = 0;
74 macdata[9] = blockCount;
75 memcpy(&macdata[10], &data[1], datalen - 1);
76 macdatalen = datalen + 9;
77 break;
78 case mtypWriteCmd:
79 memcpy(&macdata[7], &data[1], datalen - 1);
80 macdatalen = datalen + 6;
81 break;
82 case mtypWriteResp:
83 macdatalen = 1 + 6;
84 break;
85 }
c8a0f550
OM
86
87 if (verbose)
4b5d696c 88 PrintAndLog("MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen));
c8a0f550 89
4b5d696c 90 return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen);
c8a0f550
OM
91}
92
ae3340a0
OM
93int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) {
94 uint8_t data[257] = {0};
95 int datalen = 0;
96
4b5d696c 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};
ae3340a0
OM
99
100 if (session)
101 session->Authenticated = false;
102
103 uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
104 int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen);
105 if (res) {
106 PrintAndLog("ERROR exchande raw error: %d", res);
107 DropField();
108 return 2;
109 }
110
111 if (verbose)
112 PrintAndLog("<phase1: %s", sprint_hex(data, datalen));
113
114 if (datalen < 1) {
115 PrintAndLog("ERROR: card response length: %d", datalen);
116 DropField();
117 return 3;
118 }
119
120 if (data[0] != 0x90) {
121 PrintAndLog("ERROR: card response error: %02x", data[2]);
122 DropField();
123 return 3;
124 }
125
126 if (datalen != 19) { // code 1b + 16b + crc 2b
127 PrintAndLog("ERROR: card response must be 19 bytes long instead of: %d", datalen);
128 DropField();
129 return 3;
130 }
131
4b5d696c 132 aes_decode(NULL, key, &data[1], RndB, 16);
133 RndB[16] = RndB[0];
ae3340a0 134 if (verbose)
4b5d696c 135 PrintAndLog("RndB: %s", sprint_hex(RndB, 16));
ae3340a0
OM
136
137 uint8_t cmd2[33] = {0};
138 cmd2[0] = 0x72;
139
140 uint8_t raw[32] = {0};
4b5d696c 141 memmove(raw, RndA, 16);
142 memmove(&raw[16], &RndB[1], 16);
ae3340a0
OM
143
144 aes_encode(NULL, key, raw, &cmd2[1], 32);
145 if (verbose)
146 PrintAndLog(">phase2: %s", sprint_hex(cmd2, 33));
147
c8a0f550 148 res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen);
ae3340a0
OM
149 if (res) {
150 PrintAndLog("ERROR exchande raw error: %d", res);
151 DropField();
152 return 4;
153 }
154
155 if (verbose)
156 PrintAndLog("<phase2: %s", sprint_hex(data, datalen));
157
158 aes_decode(NULL, key, &data[1], raw, 32);
159
160 if (verbose) {
161 PrintAndLog("res: %s", sprint_hex(raw, 32));
4b5d696c 162 PrintAndLog("RndA`: %s", sprint_hex(&raw[4], 16));
ae3340a0
OM
163 }
164
4b5d696c 165 if (memcmp(&raw[4], &RndA[1], 16)) {
ae3340a0
OM
166 PrintAndLog("\nERROR: Authentication FAILED. rnd not equal");
167 if (verbose) {
4b5d696c 168 PrintAndLog("RndA reader: %s", sprint_hex(&RndA[1], 16));
169 PrintAndLog("RndA card: %s", sprint_hex(&raw[4], 16));
ae3340a0
OM
170 }
171 DropField();
172 return 5;
173 }
174
4b5d696c 175 if (verbose) {
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));
179 }
180
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];
186 kenc[15] = 0x11;
187
188 aes_encode(NULL, key, kenc, kenc, 16);
189 if (verbose) {
190 PrintAndLog("kenc: %s", sprint_hex(kenc, 16));
191 }
192
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];
198 kmac[15] = 0x22;
199
200 aes_encode(NULL, key, kmac, kmac, 16);
201 if (verbose) {
202 PrintAndLog("kmac: %s", sprint_hex(kmac, 16));
203 }
204
ae3340a0
OM
205 if (!leaveSignalON)
206 DropField();
207
208 if (verbose)
209 PrintAndLog("");
210
211 if (session) {
212 session->Authenticated = true;
4b5d696c 213 session->R_Ctr = 0;
214 session->W_Ctr = 0;
ae3340a0 215 session->KeyNum = keyn[1] + (keyn[0] << 8);
4b5d696c 216 memmove(session->RndA, RndA, 16);
217 memmove(session->RndB, RndB, 16);
c8a0f550 218 memmove(session->Key, key, 16);
4b5d696c 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);
ae3340a0
OM
224 }
225
226 PrintAndLog("Authentication OK");
227
228 return 0;
229}
230
c8a0f550
OM
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)
233uint8_t mfNumBlocksPerSector(uint8_t sectorNo) {
234 if (sectorNo < 32)
235 return 4;
236 else
237 return 16;
238}
239
240uint8_t mfFirstBlockOfSector(uint8_t sectorNo) {
241 if (sectorNo < 32)
242 return sectorNo * 4;
243 else
244 return 32 * 4 + (sectorNo - 32) * 16;
245}
246
247uint8_t mfSectorTrailer(uint8_t blockNo) {
248 if (blockNo < 32*4) {
249 return (blockNo | 0x03);
250 } else {
251 return (blockNo | 0x0f);
252 }
253}
254
255bool mfIsSectorTrailer(uint8_t blockNo) {
256 return (blockNo == mfSectorTrailer(blockNo));
257}
258
259uint8_t mfSectorNum(uint8_t blockNo) {
260 if (blockNo < 32 * 4)
261 return blockNo / 4;
262 else
263 return 32 + (blockNo - 32 * 4) / 16;
264
265}
Impressum, Datenschutz