]> git.zerfleddert.de Git - proxmark3-svn/blob - client/mifarehost.c
f52fb602ec28da140d4c49a7f8c1ce256694ccd1
[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 "mifarehost.h"
14
15
16 int compar_int(const void * a, const void * b) {
17 return (*(uint64_t*)b - *(uint64_t*)a);
18 }
19
20 // Compare countKeys structure
21 int compar_special_int(const void * a, const void * b) {
22 return (((countKeys *)b)->count - ((countKeys *)a)->count);
23 }
24
25 countKeys * uniqsort(uint64_t * possibleKeys, uint32_t size) {
26 int i, j = 0;
27 int count = 0;
28 countKeys *our_counts;
29
30 qsort(possibleKeys, size, sizeof (uint64_t), compar_int);
31
32 our_counts = calloc(size, sizeof(countKeys));
33 if (our_counts == NULL) {
34 PrintAndLog("Memory allocation error for our_counts");
35 return NULL;
36 }
37
38 for (i = 0; i < size; i++) {
39 if (possibleKeys[i+1] == possibleKeys[i]) {
40 count++;
41 } else {
42 our_counts[j].key = possibleKeys[i];
43 our_counts[j].count = count;
44 j++;
45 count=0;
46 }
47 }
48 qsort(our_counts, j, sizeof(countKeys), compar_special_int);
49 return (our_counts);
50 }
51
52 int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKeys)
53 {
54 int i, m, len;
55 uint8_t isEOF;
56 uint32_t uid;
57 fnVector * vector = NULL;
58 countKeys *ck;
59 int lenVector = 0;
60 UsbCommand * resp = NULL;
61
62 memset(resultKeys, 0x00, 16 * 6);
63
64 // flush queue
65 while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;
66
67 UsbCommand c = {CMD_MIFARE_NESTED, {blockNo, keyType, trgBlockNo + trgKeyType * 0x100}};
68 memcpy(c.d.asBytes, key, 6);
69 SendCommand(&c);
70
71 PrintAndLog("\n");
72
73 // wait cycle
74 while (true) {
75 printf(".");
76 if (ukbhit()) {
77 getchar();
78 printf("\naborted via keyboard!\n");
79 break;
80 }
81
82 resp = WaitForResponseTimeout(CMD_ACK, 1500);
83
84 if (resp != NULL) {
85 isEOF = resp->arg[0] & 0xff;
86
87 if (isEOF) break;
88
89 len = resp->arg[1] & 0xff;
90 if (len == 0) continue;
91
92 memcpy(&uid, resp->d.asBytes, 4);
93 PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, resp->arg[2] & 0xff, (resp->arg[2] >> 8) & 0xff);
94 vector = (fnVector *) realloc((void *)vector, (lenVector + len) * sizeof(fnVector) + 200);
95 if (vector == NULL) {
96 PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector + len, (lenVector + len) * sizeof(fnVector));
97 break;
98 }
99
100 for (i = 0; i < len; i++) {
101 vector[lenVector + i].blockNo = resp->arg[2] & 0xff;
102 vector[lenVector + i].keyType = (resp->arg[2] >> 8) & 0xff;
103 vector[lenVector + i].uid = uid;
104
105 memcpy(&vector[lenVector + i].nt, (void *)(resp->d.asBytes + 8 + i * 8 + 0), 4);
106 memcpy(&vector[lenVector + i].ks1, (void *)(resp->d.asBytes + 8 + i * 8 + 4), 4);
107 }
108
109 lenVector += len;
110 }
111 }
112
113 if (!lenVector) {
114 PrintAndLog("Got 0 keys from proxmark.");
115 return 1;
116 }
117 printf("------------------------------------------------------------------\n");
118
119 // calc keys
120 struct Crypto1State* revstate = NULL;
121 struct Crypto1State* revstate_start = NULL;
122 uint64_t lfsr;
123 int kcount = 0;
124 pKeys *pk;
125
126 if ((pk = (void *) malloc(sizeof(pKeys))) == NULL) return 1;
127 memset(pk, 0x00, sizeof(pKeys));
128
129 for (m = 0; m < lenVector; m++) {
130 // And finally recover the first 32 bits of the key
131 revstate = lfsr_recovery32(vector[m].ks1, vector[m].nt ^ vector[m].uid);
132 if (revstate_start == NULL) revstate_start = revstate;
133
134 while ((revstate->odd != 0x0) || (revstate->even != 0x0)) {
135 lfsr_rollback_word(revstate, vector[m].nt ^ vector[m].uid, 0);
136 crypto1_get_lfsr(revstate, &lfsr);
137
138 // Allocate a new space for keys
139 if (((kcount % MEM_CHUNK) == 0) || (kcount >= pk->size)) {
140 pk->size += MEM_CHUNK;
141 //fprintf(stdout, "New chunk by %d, sizeof %d\n", kcount, pk->size * sizeof(uint64_t));
142 pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t));
143 if (pk->possibleKeys == NULL) {
144 PrintAndLog("Memory allocation error for pk->possibleKeys");
145 return 1;
146 }
147 }
148 pk->possibleKeys[kcount] = lfsr;
149 kcount++;
150 revstate++;
151 }
152 free(revstate_start);
153 revstate_start = NULL;
154
155 }
156
157 // Truncate
158 if (kcount != 0) {
159 pk->size = --kcount;
160 if ((pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t))) == NULL) {
161 PrintAndLog("Memory allocation error for pk->possibleKeys");
162 return 1;
163 }
164 }
165
166 PrintAndLog("Total keys count:%d", kcount);
167 ck = uniqsort(pk->possibleKeys, pk->size);
168
169 // fill key array
170 for (i = 0; i < 16 ; i++) {
171 num_to_bytes(ck[i].key, 6, (uint8_t*)(resultKeys + i * 6));
172 }
173
174 // finalize
175 free(pk->possibleKeys);
176 free(pk);
177 free(ck);
178 free(vector);
179
180 return 0;
181 }
182
183 int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){
184 *key = 0;
185
186 UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};
187 memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
188
189 SendCommand(&c);
190
191 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 3000);
192
193 if (resp == NULL) return 1;
194 if ((resp->arg[0] & 0xff) != 0x01) return 2;
195 *key = bytes_to_num(resp->d.asBytes, 6);
196 return 0;
197 }
198
199 int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
200 UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};
201
202 SendCommand(&c);
203
204 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
205
206 if (resp == NULL) return 1;
207 memcpy(data, resp->d.asBytes, blocksCount * 16);
208 return 0;
209 }
210
211 int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
212 UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
213 memcpy(c.d.asBytes, data, blocksCount * 16);
214 SendCommand(&c);
215 return 0;
216 }
217
Impressum, Datenschutz