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