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