]> git.zerfleddert.de Git - proxmark3-svn/blame - client/mifarehost.c
fixed the mifare bug
[proxmark3-svn] / client / mifarehost.c
CommitLineData
f397b5cc
M
1// Merlok, 2011\r
2// people from mifare@nethemba.com, 2010\r
3//\r
4// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
5// at your option, any later version. See the LICENSE.txt file for the text of\r
6// the license.\r
7//-----------------------------------------------------------------------------\r
8// High frequency ISO14443A commands\r
9//-----------------------------------------------------------------------------\r
10\r
11#include <stdio.h>\r
873014de 12#include <stdlib.h> \r
31b6e9af 13#include <string.h>\r
f397b5cc
M
14#include "mifarehost.h"\r
15\r
16\r
17int compar_int(const void * a, const void * b) {\r
18 return (*(uint64_t*)b - *(uint64_t*)a);\r
19}\r
20\r
21// Compare countKeys structure\r
22int compar_special_int(const void * a, const void * b) {\r
23 return (((countKeys *)b)->count - ((countKeys *)a)->count);\r
24}\r
25\r
26countKeys * uniqsort(uint64_t * possibleKeys, uint32_t size) {\r
27 int i, j = 0;\r
28 int count = 0;\r
29 countKeys *our_counts;\r
30 \r
31 qsort(possibleKeys, size, sizeof (uint64_t), compar_int);\r
32 \r
33 our_counts = calloc(size, sizeof(countKeys));\r
34 if (our_counts == NULL) {\r
35 PrintAndLog("Memory allocation error for our_counts");\r
36 return NULL;\r
37 }\r
38 \r
39 for (i = 0; i < size; i++) {\r
40 if (possibleKeys[i+1] == possibleKeys[i]) { \r
41 count++;\r
42 } else {\r
43 our_counts[j].key = possibleKeys[i];\r
44 our_counts[j].count = count;\r
45 j++;\r
46 count=0;\r
47 }\r
48 }\r
49 qsort(our_counts, j, sizeof(countKeys), compar_special_int);\r
50 return (our_counts);\r
51}\r
52\r
53int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKeys) \r
54{\r
55 int i, m, len;\r
56 uint8_t isEOF;\r
57 uint32_t uid;\r
58 fnVector * vector = NULL;\r
59 countKeys *ck;\r
60 int lenVector = 0;\r
61 UsbCommand * resp = NULL;\r
62 \r
63 memset(resultKeys, 0x00, 16 * 6);\r
64\r
65 // flush queue\r
66 while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;\r
67 \r
68 UsbCommand c = {CMD_MIFARE_NESTED, {blockNo, keyType, trgBlockNo + trgKeyType * 0x100}};\r
69 memcpy(c.d.asBytes, key, 6);\r
70 SendCommand(&c);\r
71\r
72 PrintAndLog("\n");\r
73\r
74 // wait cycle\r
75 while (true) {\r
76 printf(".");\r
77 if (ukbhit()) {\r
78 getchar();\r
79 printf("\naborted via keyboard!\n");\r
80 break;\r
81 }\r
82\r
83 resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
84\r
85 if (resp != NULL) {\r
86 isEOF = resp->arg[0] & 0xff;\r
87\r
88 if (isEOF) break;\r
89 \r
90 len = resp->arg[1] & 0xff;\r
91 if (len == 0) continue;\r
92 \r
93 memcpy(&uid, resp->d.asBytes, 4); \r
94 PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, resp->arg[2] & 0xff, (resp->arg[2] >> 8) & 0xff);\r
95 vector = (fnVector *) realloc((void *)vector, (lenVector + len) * sizeof(fnVector) + 200);\r
96 if (vector == NULL) {\r
97 PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector + len, (lenVector + len) * sizeof(fnVector)); \r
98 break;\r
99 }\r
100 \r
101 for (i = 0; i < len; i++) {\r
102 vector[lenVector + i].blockNo = resp->arg[2] & 0xff;\r
103 vector[lenVector + i].keyType = (resp->arg[2] >> 8) & 0xff;\r
104 vector[lenVector + i].uid = uid;\r
105\r
106 memcpy(&vector[lenVector + i].nt, (void *)(resp->d.asBytes + 8 + i * 8 + 0), 4);\r
107 memcpy(&vector[lenVector + i].ks1, (void *)(resp->d.asBytes + 8 + i * 8 + 4), 4);\r
108 }\r
109\r
110 lenVector += len;\r
111 }\r
112 }\r
113 \r
114 if (!lenVector) {\r
115 PrintAndLog("Got 0 keys from proxmark."); \r
116 return 1;\r
117 }\r
118 printf("------------------------------------------------------------------\n");\r
119 \r
120 // calc keys\r
121 struct Crypto1State* revstate = NULL;\r
122 struct Crypto1State* revstate_start = NULL;\r
123 uint64_t lfsr;\r
124 int kcount = 0;\r
125 pKeys *pk;\r
126 \r
127 if ((pk = (void *) malloc(sizeof(pKeys))) == NULL) return 1;\r
128 memset(pk, 0x00, sizeof(pKeys));\r
129 \r
130 for (m = 0; m < lenVector; m++) {\r
131 // And finally recover the first 32 bits of the key\r
132 revstate = lfsr_recovery32(vector[m].ks1, vector[m].nt ^ vector[m].uid);\r
133 if (revstate_start == NULL) revstate_start = revstate;\r
134 \r
135 while ((revstate->odd != 0x0) || (revstate->even != 0x0)) {\r
136 lfsr_rollback_word(revstate, vector[m].nt ^ vector[m].uid, 0);\r
137 crypto1_get_lfsr(revstate, &lfsr);\r
138\r
139 // Allocate a new space for keys\r
140 if (((kcount % MEM_CHUNK) == 0) || (kcount >= pk->size)) {\r
141 pk->size += MEM_CHUNK;\r
142//fprintf(stdout, "New chunk by %d, sizeof %d\n", kcount, pk->size * sizeof(uint64_t));\r
143 pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t));\r
144 if (pk->possibleKeys == NULL) {\r
145 PrintAndLog("Memory allocation error for pk->possibleKeys"); \r
146 return 1;\r
147 }\r
148 }\r
149 pk->possibleKeys[kcount] = lfsr;\r
150 kcount++;\r
151 revstate++;\r
152 }\r
153 free(revstate_start);\r
154 revstate_start = NULL;\r
155\r
156 }\r
157 \r
158 // Truncate\r
159 if (kcount != 0) {\r
160 pk->size = --kcount;\r
161 if ((pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t))) == NULL) {\r
162 PrintAndLog("Memory allocation error for pk->possibleKeys"); \r
163 return 1;\r
164 } \r
165 }\r
166\r
167 PrintAndLog("Total keys count:%d", kcount);\r
168 ck = uniqsort(pk->possibleKeys, pk->size);\r
169\r
170 // fill key array\r
171 for (i = 0; i < 16 ; i++) {\r
172 num_to_bytes(ck[i].key, 6, (uint8_t*)(resultKeys + i * 6));\r
173 }\r
174\r
175 // finalize\r
176 free(pk->possibleKeys);\r
177 free(pk);\r
178 free(ck);\r
179 free(vector);\r
180\r
181 return 0;\r
182}\r
183\r
184int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){\r
185 *key = 0;\r
186\r
187 UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};\r
188 memcpy(c.d.asBytes, keyBlock, 6 * keycnt);\r
189\r
190 SendCommand(&c);\r
191\r
192 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 3000);\r
193\r
194 if (resp == NULL) return 1;\r
195 if ((resp->arg[0] & 0xff) != 0x01) return 2;\r
196 *key = bytes_to_num(resp->d.asBytes, 6);\r
197 return 0;\r
198}\r
8556b852
M
199\r
200int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
545a1f38 201 UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
8556b852 202 \r
545a1f38 203 SendCommand(&c);\r
8556b852
M
204\r
205 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
206\r
207 if (resp == NULL) return 1;\r
208 memcpy(data, resp->d.asBytes, blocksCount * 16); \r
209 return 0;\r
210}\r
211\r
212int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
545a1f38 213 UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};\r
8556b852 214 memcpy(c.d.asBytes, data, blocksCount * 16); \r
545a1f38 215 SendCommand(&c);\r
8556b852
M
216 return 0;\r
217}\r
218\r
0675f200 219int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) {\r
0675f200
M
220 uint8_t block0[16];\r
221 memset(block0, 0, 16);\r
222 memcpy(block0, uid, 4); \r
223 block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC\r
f774db95 224 \r
208a0166 225 return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);\r
f774db95
M
226}\r
227\r
208a0166 228int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params) {\r
f774db95 229 uint8_t isOK = 0;\r
0675f200 230\r
545a1f38 231 UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};\r
f774db95 232 memcpy(c.d.asBytes, data, 16); \r
545a1f38 233 SendCommand(&c);\r
0675f200
M
234\r
235 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
236\r
237 if (resp != NULL) {\r
238 isOK = resp->arg[0] & 0xff;\r
208a0166 239 if (uid != NULL) memcpy(uid, resp->d.asBytes, 4); \r
0675f200
M
240 if (!isOK) return 2;\r
241 } else {\r
242 PrintAndLog("Command execute timeout");\r
243 return 1;\r
244 }\r
245 return 0;\r
246}\r
545a1f38
M
247\r
248int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {\r
249 uint8_t isOK = 0;\r
250\r
251 UsbCommand c = {CMD_MIFARE_EML_CGETBLOCK, {params, 0, blockNo}};\r
252 SendCommand(&c);\r
253\r
254 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
255\r
256 if (resp != NULL) {\r
257 isOK = resp->arg[0] & 0xff;\r
258 memcpy(data, resp->d.asBytes, 16); \r
259 if (!isOK) return 2;\r
260 } else {\r
261 PrintAndLog("Command execute timeout");\r
262 return 1;\r
263 }\r
264 return 0;\r
265}\r
Impressum, Datenschutz