]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/mifarehost.c
   2 // people from mifare@nethemba.com, 2010 
   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 
   7 //----------------------------------------------------------------------------- 
   9 //----------------------------------------------------------------------------- 
  14 #include "mifarehost.h" 
  15 #include "proxmark3.h" 
  18 int compar_int(const void * a
, const void * b
) { 
  19         return (*(uint64_t*)b 
- *(uint64_t*)a
); 
  22 // Compare countKeys structure 
  23 int compar_special_int(const void * a
, const void * b
) { 
  24         return (((countKeys 
*)b
)->count 
- ((countKeys 
*)a
)->count
); 
  27 countKeys 
* uniqsort(uint64_t * possibleKeys
, uint32_t size
) { 
  30         countKeys 
*our_counts
; 
  32         qsort(possibleKeys
, size
, sizeof (uint64_t), compar_int
); 
  34         our_counts 
= calloc(size
, sizeof(countKeys
)); 
  35         if (our_counts 
== NULL
) { 
  36                 PrintAndLog("Memory allocation error for our_counts"); 
  40         for (i 
= 0; i 
< size
; i
++) { 
  41         if (possibleKeys
[i
+1] == possibleKeys
[i
]) {  
  44                         our_counts
[j
].key 
= possibleKeys
[i
]; 
  45                         our_counts
[j
].count 
= count
; 
  50         qsort(our_counts
, j
, sizeof(countKeys
), compar_special_int
); 
  54 int mfnested(uint8_t blockNo
, uint8_t keyType
, uint8_t * key
, uint8_t trgBlockNo
, uint8_t trgKeyType
, uint8_t * resultKeys
)  
  59         fnVector 
* vector 
= NULL
; 
  64         memset(resultKeys
, 0x00, 16 * 6); 
  67         WaitForResponseTimeout(CMD_ACK
,NULL
,100); 
  69   UsbCommand c 
= {CMD_MIFARE_NESTED
, {blockNo
, keyType
, trgBlockNo 
+ trgKeyType 
* 0x100}}; 
  70         memcpy(c
.d
.asBytes
, key
, 6); 
  80                         printf("\naborted via keyboard!\n"); 
  84                 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
  85                         isEOF  
= resp
.arg
[0] & 0xff; 
  89                         len 
= resp
.arg
[1] & 0xff; 
  90                         if (len 
== 0) continue; 
  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); 
  96                                 PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector 
+ len
, (lenVector 
+ len
) * sizeof(fnVector
));  
 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
; 
 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); 
 114                 PrintAndLog("Got 0 keys from proxmark.");  
 117         printf("------------------------------------------------------------------\n"); 
 120         struct Crypto1State
* revstate 
= NULL
; 
 121         struct Crypto1State
* revstate_start 
= NULL
; 
 126         if ((pk 
= (void *) malloc(sizeof(pKeys
))) == NULL
) return 1; 
 127         memset(pk
, 0x00, sizeof(pKeys
)); 
 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
; 
 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
); 
 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");  
 148                         pk
->possibleKeys
[kcount
] = lfsr
; 
 152         free(revstate_start
); 
 153         revstate_start 
= NULL
; 
 160                 if ((pk
->possibleKeys 
= (uint64_t *) realloc((void *)pk
->possibleKeys
, pk
->size 
* sizeof(uint64_t))) == NULL
) { 
 161                         PrintAndLog("Memory allocation error for pk->possibleKeys");  
 166         PrintAndLog("Total keys count:%d", kcount
); 
 167         ck 
= uniqsort(pk
->possibleKeys
, pk
->size
); 
 170         for (i 
= 0; i 
< 16 ; i
++) { 
 171                 num_to_bytes(ck
[i
].key
, 6, (uint8_t*)(resultKeys 
+ i 
* 6)); 
 175         free(pk
->possibleKeys
); 
 183 int mfCheckKeys (uint8_t blockNo
, uint8_t keyType
, uint8_t keycnt
, uint8_t * keyBlock
, uint64_t * key
){ 
 186   UsbCommand c 
= {CMD_MIFARE_CHKKEYS
, {blockNo
, keyType
, keycnt
}}; 
 187         memcpy(c
.d
.asBytes
, keyBlock
, 6 * keycnt
); 
 191         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) return 1; 
 192         if ((resp
.arg
[0] & 0xff) != 0x01) return 2; 
 193         *key 
= bytes_to_num(resp
.d
.asBytes
, 6); 
 199 int mfEmlGetMem(uint8_t *data
, int blockNum
, int blocksCount
) { 
 200         UsbCommand c 
= {CMD_MIFARE_EML_MEMGET
, {blockNum
, blocksCount
, 0}}; 
 204         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) return 1; 
 205         memcpy(data
, resp
.d
.asBytes
, blocksCount 
* 16); 
 209 int mfEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) { 
 210         UsbCommand c 
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}}; 
 211         memcpy(c
.d
.asBytes
, data
, blocksCount 
* 16);  
 218 int mfCSetUID(uint8_t *uid
, uint8_t *oldUID
, int wantWipe
) { 
 220         memset(block0
, 0, 16); 
 221         memcpy(block0
, uid
, 4);  
 222         block0
[4] = block0
[0]^block0
[1]^block0
[2]^block0
[3]; // Mifare UID BCC 
 223         // mifare classic SAK(byte 5) and ATQA(byte 6 and 7) 
 228         return mfCSetBlock(0, block0
, oldUID
, wantWipe
, CSETBLOCK_SINGLE_OPER
); 
 231 int mfCSetBlock(uint8_t blockNo
, uint8_t *data
, uint8_t *uid
, int wantWipe
, uint8_t params
) { 
 234         UsbCommand c 
= {CMD_MIFARE_EML_CSETBLOCK
, {wantWipe
, params 
& (0xFE | (uid 
== NULL 
? 0:1)), blockNo
}}; 
 235         memcpy(c
.d
.asBytes
, data
, 16);  
 239         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 240                 isOK  
= resp
.arg
[0] & 0xff; 
 241                 if (uid 
!= NULL
) memcpy(uid
, resp
.d
.asBytes
, 4); 
 244                 PrintAndLog("Command execute timeout"); 
 250 int mfCGetBlock(uint8_t blockNo
, uint8_t *data
, uint8_t params
) { 
 253         UsbCommand c 
= {CMD_MIFARE_EML_CGETBLOCK
, {params
, 0, blockNo
}}; 
 257         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 258                 isOK  
= resp
.arg
[0] & 0xff; 
 259                 memcpy(data
, resp
.d
.asBytes
, 16); 
 262                 PrintAndLog("Command execute timeout"); 
 271 static uint8_t trailerAccessBytes
[4] = {0x08, 0x77, 0x8F, 0x00}; 
 274 char logHexFileName
[200] = {0x00}; 
 275 static uint8_t traceCard
[4096] = {0x00}; 
 276 static char traceFileName
[20]; 
 277 static int traceState 
= TRACE_IDLE
; 
 278 static uint8_t traceCurBlock 
= 0; 
 279 static uint8_t traceCurKey 
= 0; 
 281 struct Crypto1State 
*traceCrypto1 
= NULL
; 
 283 struct Crypto1State 
*revstate
; 
 288 uint32_t uid
;     // serial number 
 289 uint32_t nt
;      // tag challenge 
 291 uint32_t nr_enc
;  // encrypted reader challenge 
 292 uint32_t ar_enc
;  // encrypted reader response 
 294 uint32_t at_enc
;  // encrypted tag response 
 297 int isTraceCardEmpty(void) { 
 298         return ((traceCard
[0] == 0) && (traceCard
[1] == 0) && (traceCard
[2] == 0) && (traceCard
[3] == 0)); 
 301 int isBlockEmpty(int blockN
) { 
 302         for (int i 
= 0; i 
< 16; i
++)  
 303                 if (traceCard
[blockN 
* 16 + i
] != 0) return 0; 
 308 int isBlockTrailer(int blockN
) { 
 309  return ((blockN 
& 0x03) == 0x03); 
 312 int loadTraceCard(uint8_t *tuid
) { 
 318         if (!isTraceCardEmpty()) saveTraceCard(); 
 319         memset(traceCard
, 0x00, 4096); 
 320         memcpy(traceCard
, tuid 
+ 3, 4); 
 321         FillFileNameByUID(traceFileName
, tuid
, ".eml", 7); 
 323         f 
= fopen(traceFileName
, "r"); 
 328                 memset(buf
, 0, sizeof(buf
)); 
 329                 if (fgets(buf
, sizeof(buf
), f
) == NULL
) { 
 330       PrintAndLog("File reading error."); 
 334                 if (strlen(buf
) < 32){ 
 336                         PrintAndLog("File content error. Block data must include 32 HEX symbols"); 
 339                 for (i 
= 0; i 
< 32; i 
+= 2) 
 340                         sscanf(&buf
[i
], "%02x", (unsigned int *)&buf8
[i 
/ 2]); 
 342                 memcpy(traceCard 
+ blockNum 
* 16, buf8
, 16); 
 351 int saveTraceCard(void) { 
 354         if ((!strlen(traceFileName
)) || (isTraceCardEmpty())) return 0; 
 356         f 
= fopen(traceFileName
, "w+"); 
 357         for (int i 
= 0; i 
< 64; i
++) {  // blocks 
 358                 for (int j 
= 0; j 
< 16; j
++)  // bytes 
 359                         fprintf(f
, "%02x", *(traceCard 
+ i 
* 16 + j
));  
 367 int mfTraceInit(uint8_t *tuid
, uint8_t *atqa
, uint8_t sak
, bool wantSaveToEmlFile
) { 
 369         if (traceCrypto1
) crypto1_destroy(traceCrypto1
); 
 372         if (wantSaveToEmlFile
) loadTraceCard(tuid
); 
 373         traceCard
[4] = traceCard
[0] ^ traceCard
[1] ^ traceCard
[2] ^ traceCard
[3]; 
 375         memcpy(&traceCard
[6], atqa
, 2); 
 377         uid 
= bytes_to_num(tuid 
+ 3, 4); 
 379         traceState 
= TRACE_IDLE
; 
 384 void mf_crypto1_decrypt(struct Crypto1State 
*pcs
, uint8_t *data
, int len
, bool isEncrypted
){ 
 389                 for (i 
= 0; i 
< len
; i
++) 
 390                         data
[i
] = crypto1_byte(pcs
, 0x00, isEncrypted
) ^ data
[i
]; 
 393                 for (i 
= 0; i 
< 4; i
++) 
 394                         bt 
|= (crypto1_bit(pcs
, 0, isEncrypted
) ^ BIT(data
[0], i
)) << i
; 
 402 int mfTraceDecode(uint8_t *data_src
, int len
, uint32_t parity
, bool wantSaveToEmlFile
) { 
 405         if (traceState 
== TRACE_ERROR
) return 1; 
 407                 traceState 
= TRACE_ERROR
; 
 411         memcpy(data
, data_src
, len
); 
 412         if ((traceCrypto1
) && ((traceState 
== TRACE_IDLE
) || (traceState 
> TRACE_AUTH_OK
))) { 
 413                 mf_crypto1_decrypt(traceCrypto1
, data
, len
, 0); 
 414                 PrintAndLog("dec> %s", sprint_hex(data
, len
)); 
 415                 AddLogHex(logHexFileName
, "dec> ", data
, len
);  
 418         switch (traceState
) { 
 420                 // check packet crc16! 
 421                 if ((len 
>= 4) && (!CheckCrc14443(CRC_14443_A
, data
, len
))) { 
 422                         PrintAndLog("dec> CRC ERROR!!!"); 
 423                         AddLogLine(logHexFileName
, "dec> ", "CRC ERROR!!!");  
 424                         traceState 
= TRACE_ERROR
;  // do not decrypt the next commands 
 429                 if ((len 
==4) && ((data
[0] == 0x60) || (data
[0] == 0x61))) { 
 430                         traceState 
= TRACE_AUTH1
; 
 431                         traceCurBlock 
= data
[1]; 
 432                         traceCurKey 
= data
[0] == 60 ? 1:0; 
 437                 if ((len 
==4) && ((data
[0] == 0x30))) { 
 438                         traceState 
= TRACE_READ_DATA
; 
 439                         traceCurBlock 
= data
[1]; 
 444                 if ((len 
==4) && ((data
[0] == 0xA0))) { 
 445                         traceState 
= TRACE_WRITE_OK
; 
 446                         traceCurBlock 
= data
[1]; 
 451                 if ((len 
==4) && ((data
[0] == 0x50) && (data
[1] == 0x00))) { 
 452                         traceState 
= TRACE_ERROR
;  // do not decrypt the next commands 
 459         case TRACE_READ_DATA
:  
 461                         traceState 
= TRACE_IDLE
; 
 463                         if (isBlockTrailer(traceCurBlock
)) { 
 464                                 memcpy(traceCard 
+ traceCurBlock 
* 16 + 6, data 
+ 6, 4); 
 466                                 memcpy(traceCard 
+ traceCurBlock 
* 16, data
, 16); 
 468                         if (wantSaveToEmlFile
) saveTraceCard(); 
 471                         traceState 
= TRACE_ERROR
; 
 477                 if ((len 
== 1) && (data
[0] = 0x0a)) { 
 478                         traceState 
= TRACE_WRITE_DATA
; 
 482                         traceState 
= TRACE_ERROR
; 
 487         case TRACE_WRITE_DATA
:  
 489                         traceState 
= TRACE_IDLE
; 
 491                         memcpy(traceCard 
+ traceCurBlock 
* 16, data
, 16); 
 492                         if (wantSaveToEmlFile
) saveTraceCard(); 
 495                         traceState 
= TRACE_ERROR
; 
 502                         traceState 
= TRACE_AUTH2
; 
 504                         nt 
= bytes_to_num(data
, 4); 
 508                         traceState 
= TRACE_ERROR
; 
 515                         traceState 
= TRACE_AUTH_OK
; 
 517                         nr_enc 
= bytes_to_num(data
, 4); 
 518                         ar_enc 
= bytes_to_num(data 
+ 4, 4); 
 522                         traceState 
= TRACE_ERROR
; 
 529                         traceState 
= TRACE_IDLE
; 
 531                         at_enc 
= bytes_to_num(data
, 4); 
 536                                 ks2 
= ar_enc 
^ prng_successor(nt
, 64); 
 537                                 ks3 
= at_enc 
^ prng_successor(nt
, 96); 
 538                                 revstate 
= lfsr_recovery64(ks2
, ks3
); 
 539                                 lfsr_rollback_word(revstate
, 0, 0); 
 540                                 lfsr_rollback_word(revstate
, 0, 0); 
 541                                 lfsr_rollback_word(revstate
, nr_enc
, 1); 
 542                                 lfsr_rollback_word(revstate
, uid 
^ nt
, 0); 
 544                                 ks2 
= ar_enc 
^ prng_successor(nt
, 64); 
 545                                 ks3 
= at_enc 
^ prng_successor(nt
, 96); 
 546                                 revstate 
= lfsr_recovery64(ks2
, ks3
); 
 547                                 lfsr_rollback_word(revstate
, 0, 0); 
 548                                 lfsr_rollback_word(revstate
, 0, 0); 
 549                                 lfsr_rollback_word(revstate
, nr_enc
, 1); 
 550                                 lfsr_rollback_word(revstate
, uid 
^ nt
, 0); 
 552                         crypto1_get_lfsr(revstate
, &lfsr
); 
 553                         printf("key> %x%x\n", (unsigned int)((lfsr 
& 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr 
& 0xFFFFFFFF)); 
 554                         AddLogUint64(logHexFileName
, "key> ", lfsr
);  
 556                         int blockShift 
= ((traceCurBlock 
& 0xFC) + 3) * 16; 
 557                         if (isBlockEmpty((traceCurBlock 
& 0xFC) + 3)) memcpy(traceCard 
+ blockShift 
+ 6, trailerAccessBytes
, 4); 
 560                                 num_to_bytes(lfsr
, 6, traceCard 
+ blockShift 
+ 10); 
 562                                 num_to_bytes(lfsr
, 6, traceCard 
+ blockShift
); 
 564                         if (wantSaveToEmlFile
) saveTraceCard(); 
 567                                 crypto1_destroy(traceCrypto1
); 
 570                         // set cryptosystem state 
 571                         traceCrypto1 
= lfsr_recovery64(ks2
, ks3
); 
 573 //      nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt; 
 575         /*      traceCrypto1 = crypto1_create(lfsr); // key in lfsr 
 576                 crypto1_word(traceCrypto1, nt ^ uid, 0); 
 577                 crypto1_word(traceCrypto1, ar, 1); 
 578                 crypto1_word(traceCrypto1, 0, 0); 
 579                 crypto1_word(traceCrypto1, 0, 0);*/ 
 583                         traceState 
= TRACE_ERROR
; 
 589                 traceState 
= TRACE_ERROR
;