]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/mifarehost.c
Fixed writing em410x 40bits UID on T5555/T55x7 tags on 32bits systems
[proxmark3-svn] / client / mifarehost.c
CommitLineData
b62a5a84 1// Merlok, 2011, 2012\r
f397b5cc
M
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
8784cd1a
M
224 // mifare classic SAK(byte 5) and ATQA(byte 6 and 7)\r
225 block0[5] = 0x88;\r
226 block0[6] = 0x04;\r
227 block0[7] = 0x00;\r
f774db95 228 \r
208a0166 229 return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);\r
f774db95
M
230}\r
231\r
208a0166 232int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params) {\r
f774db95 233 uint8_t isOK = 0;\r
0675f200 234\r
545a1f38 235 UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};\r
f774db95 236 memcpy(c.d.asBytes, data, 16); \r
545a1f38 237 SendCommand(&c);\r
0675f200
M
238\r
239 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
240\r
241 if (resp != NULL) {\r
242 isOK = resp->arg[0] & 0xff;\r
208a0166 243 if (uid != NULL) memcpy(uid, resp->d.asBytes, 4); \r
0675f200
M
244 if (!isOK) return 2;\r
245 } else {\r
246 PrintAndLog("Command execute timeout");\r
247 return 1;\r
248 }\r
249 return 0;\r
250}\r
545a1f38
M
251\r
252int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {\r
253 uint8_t isOK = 0;\r
254\r
255 UsbCommand c = {CMD_MIFARE_EML_CGETBLOCK, {params, 0, blockNo}};\r
256 SendCommand(&c);\r
257\r
258 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
259\r
260 if (resp != NULL) {\r
261 isOK = resp->arg[0] & 0xff;\r
262 memcpy(data, resp->d.asBytes, 16); \r
263 if (!isOK) return 2;\r
264 } else {\r
265 PrintAndLog("Command execute timeout");\r
266 return 1;\r
267 }\r
268 return 0;\r
269}\r
Impressum, Datenschutz