mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
fix to darkside overdue. I needed to remove my old impl..
This commit is contained in:
parent
f59ee2ffeb
commit
1f637d726f
17 changed files with 385 additions and 1598 deletions
100
client/mfkey.c
100
client/mfkey.c
|
@ -10,7 +10,83 @@
|
|||
// MIFARE Darkside hack
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "mfkey.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
|
||||
// MIFARE
|
||||
int compare_uint64(const void *a, const void *b) {
|
||||
if (*(uint64_t*)b == *(uint64_t*)a) return 0;
|
||||
if (*(uint64_t*)b < *(uint64_t*)a) return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the intersection (common members) of two sorted lists. Lists are terminated by -1. Result will be in list1. Number of elements is returned.
|
||||
uint32_t intersection(uint64_t *listA, uint64_t *listB) {
|
||||
if (listA == NULL || listB == NULL)
|
||||
return 0;
|
||||
|
||||
uint64_t *p1, *p2, *p3;
|
||||
p1 = p3 = listA;
|
||||
p2 = listB;
|
||||
|
||||
while ( *p1 != -1 && *p2 != -1 ) {
|
||||
if (compare_uint64(p1, p2) == 0) {
|
||||
*p3++ = *p1++;
|
||||
p2++;
|
||||
}
|
||||
else {
|
||||
while (compare_uint64(p1, p2) == -1) ++p1;
|
||||
while (compare_uint64(p1, p2) == 1) ++p2;
|
||||
}
|
||||
}
|
||||
*p3 = -1;
|
||||
return p3 - listA;
|
||||
}
|
||||
|
||||
// Darkside attack (hf mf mifare)
|
||||
// if successful it will return a list of keys, not just one.
|
||||
uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
|
||||
struct Crypto1State *states;
|
||||
uint32_t i, pos, rr = 0;
|
||||
uint8_t bt, ks3x[8], par[8][8];
|
||||
uint64_t key_recovered;
|
||||
static uint64_t *keylist;
|
||||
|
||||
// Reset the last three significant bits of the reader nonce
|
||||
nr &= 0xFFFFFF1F;
|
||||
|
||||
for ( pos = 0; pos < 8; pos++ ) {
|
||||
ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0F;
|
||||
bt = (par_info >> (pos*8)) & 0xFF;
|
||||
|
||||
par[7-pos][0] = (bt >> 0) & 1;
|
||||
par[7-pos][1] = (bt >> 1) & 1;
|
||||
par[7-pos][2] = (bt >> 2) & 1;
|
||||
par[7-pos][3] = (bt >> 3) & 1;
|
||||
par[7-pos][4] = (bt >> 4) & 1;
|
||||
par[7-pos][5] = (bt >> 5) & 1;
|
||||
par[7-pos][6] = (bt >> 6) & 1;
|
||||
par[7-pos][7] = (bt >> 7) & 1;
|
||||
}
|
||||
|
||||
states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0));
|
||||
|
||||
if (!states) {
|
||||
printf("Failed getting states\n");
|
||||
*keys = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
keylist = (uint64_t*)states;
|
||||
|
||||
for (i = 0; keylist[i]; i++) {
|
||||
lfsr_rollback_word(states+i, uid^nt, 0);
|
||||
crypto1_get_lfsr(states+i, &key_recovered);
|
||||
keylist[i] = key_recovered;
|
||||
}
|
||||
keylist[i] = -1;
|
||||
|
||||
*keys = keylist;
|
||||
return i;
|
||||
}
|
||||
|
||||
// recover key from 2 different reader responses on same tag challenge
|
||||
bool mfkey32(nonces_t data, uint64_t *outputkey) {
|
||||
|
@ -20,7 +96,9 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
|
|||
bool isSuccess = false;
|
||||
uint8_t counter = 0;
|
||||
|
||||
s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
|
||||
uint32_t p640 = prng_successor(data.nonce, 64);
|
||||
uint32_t p641 = prng_successor(data.nonce2, 64);
|
||||
s = lfsr_recovery32(data.ar ^ p640, 0);
|
||||
|
||||
for(t = s; t->odd | t->even; ++t) {
|
||||
lfsr_rollback_word(t, 0, 0);
|
||||
|
@ -29,7 +107,7 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
|
|||
crypto1_get_lfsr(t, &key);
|
||||
crypto1_word(t, data.cuid ^ data.nonce, 0);
|
||||
crypto1_word(t, data.nr2, 1);
|
||||
if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce, 64))) {
|
||||
if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) {
|
||||
outkey = key;
|
||||
counter++;
|
||||
if (counter == 20) break;
|
||||
|
@ -42,14 +120,17 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
|
|||
}
|
||||
|
||||
// recover key from 2 reader responses on 2 different tag challenges
|
||||
// skip "several found keys". Only return true if ONE key is found
|
||||
bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
|
||||
struct Crypto1State *s, *t;
|
||||
uint64_t outkey = 0;
|
||||
uint64_t key = 0; // recovered key
|
||||
bool isSuccess = false;
|
||||
int counter = 0;
|
||||
|
||||
s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
|
||||
uint32_t p640 = prng_successor(data.nonce, 64);
|
||||
uint32_t p641 = prng_successor(data.nonce2, 64);
|
||||
|
||||
s = lfsr_recovery32(data.ar ^ p640, 0);
|
||||
|
||||
for(t = s; t->odd | t->even; ++t) {
|
||||
lfsr_rollback_word(t, 0, 0);
|
||||
|
@ -59,11 +140,10 @@ bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
|
|||
|
||||
crypto1_word(t, data.cuid ^ data.nonce2, 0);
|
||||
crypto1_word(t, data.nr2, 1);
|
||||
if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce2, 64))) {
|
||||
outkey=key;
|
||||
if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) {
|
||||
outkey = key;
|
||||
++counter;
|
||||
if (counter==20)
|
||||
break;
|
||||
if (counter == 20) break;
|
||||
}
|
||||
}
|
||||
isSuccess = (counter == 1);
|
||||
|
@ -92,5 +172,3 @@ int mfkey64(nonces_t data, uint64_t *outputkey){
|
|||
*outputkey = key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue