mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-23 22:45:27 -07:00
implementing hf mf hardnested
- implemented nonce file reading (hf mf hardnested r) - implemented function to calculate the sum property of nonces - implemented functions to calculate the partial sum properties of crypto states - for testing only: calculate sum property of random crypto states and show probability distribution
This commit is contained in:
parent
1da61a02fe
commit
00950b1c16
1 changed files with 190 additions and 9 deletions
|
@ -194,6 +194,137 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
|
|||
}
|
||||
|
||||
|
||||
typedef struct noncelistentry {
|
||||
uint32_t NonceAndPar; // concatenated last 24 bits of nonce and parity
|
||||
void *next;
|
||||
} noncelistentry_t;
|
||||
|
||||
|
||||
typedef struct noncelist {
|
||||
uint16_t num;
|
||||
uint8_t Sum;
|
||||
noncelistentry_t *first;
|
||||
} noncelist_t;
|
||||
|
||||
|
||||
noncelist_t nonces[256];
|
||||
uint16_t first_byte_Sum = 0;
|
||||
uint16_t first_byte_num = 0;
|
||||
|
||||
|
||||
int add_nonce(uint32_t nonce, uint8_t par)
|
||||
{
|
||||
uint8_t first_byte = nonce >> 24;
|
||||
uint32_t NonceAndPar = (nonce << 8) | (par & 0x07);
|
||||
noncelistentry_t *p1 = nonces[first_byte].first;
|
||||
noncelistentry_t *p2 = NULL;
|
||||
|
||||
if (p1 == NULL) { // first nonce with this 1st byte
|
||||
first_byte_num++;
|
||||
first_byte_Sum += parity((nonce & 0xff000000) | (par & 0x08)); // 1st byte sum property
|
||||
}
|
||||
|
||||
while (p1 != NULL && p1->NonceAndPar < NonceAndPar) {
|
||||
p2 = p1;
|
||||
p1 = p1->next;
|
||||
}
|
||||
|
||||
if (p1 == NULL) { // need to add at the end of the list
|
||||
if (p2 == NULL) { // list is empty yet
|
||||
p2 = nonces[first_byte].first = malloc(sizeof(noncelistentry_t));
|
||||
} else {
|
||||
p2 = p2->next = malloc(sizeof(noncelistentry_t));
|
||||
}
|
||||
} else if (p1->NonceAndPar != NonceAndPar) { // quite unlikely for hardened cards, but don't want to add a nonce twice
|
||||
if (p2 == NULL) { // need to insert at start of list
|
||||
p2 = nonces[first_byte].first = malloc(sizeof(noncelistentry_t));
|
||||
} else {
|
||||
p2 = p2->next = malloc(sizeof(noncelistentry_t));
|
||||
}
|
||||
} else {
|
||||
return (first_byte_num==256?first_byte_Sum:-1);
|
||||
}
|
||||
|
||||
p2->next = p1;
|
||||
p2->NonceAndPar = NonceAndPar;
|
||||
nonces[first_byte].num++;
|
||||
nonces[first_byte].Sum += parity(NonceAndPar & 0xff000004); // 2nd byte sum property
|
||||
|
||||
return (first_byte_num==256?first_byte_Sum:-1);
|
||||
}
|
||||
|
||||
|
||||
uint16_t SumPropertyOdd(struct Crypto1State *s)
|
||||
{
|
||||
uint16_t oddsum = 0;
|
||||
for (uint16_t j = 0; j < 16; j++) {
|
||||
uint32_t oddstate = s->odd;
|
||||
uint16_t part_sum = 0;
|
||||
for (uint16_t i = 0; i < 5; i++) {
|
||||
part_sum ^= filter(oddstate);
|
||||
oddstate = (oddstate << 1) | ((j >> (3-i)) & 0x01) ;
|
||||
}
|
||||
oddsum += part_sum;
|
||||
}
|
||||
return oddsum;
|
||||
}
|
||||
|
||||
|
||||
uint16_t SumPropertyEven(struct Crypto1State *s)
|
||||
{
|
||||
uint16_t evensum = 0;
|
||||
for (uint16_t j = 0; j < 16; j++) {
|
||||
uint32_t evenstate = s->even;
|
||||
uint16_t part_sum = 0;
|
||||
for (uint16_t i = 0; i < 4; i++) {
|
||||
evenstate = (evenstate << 1) | ((j >> (3-i)) & 0x01) ;
|
||||
part_sum ^= filter(evenstate);
|
||||
}
|
||||
evensum += part_sum;
|
||||
}
|
||||
return evensum;
|
||||
}
|
||||
|
||||
|
||||
uint16_t SumProperty(struct Crypto1State *s)
|
||||
{
|
||||
uint16_t sum_odd = SumPropertyOdd(s);
|
||||
uint16_t sum_even = SumPropertyEven(s);
|
||||
return (sum_odd*(16-sum_even) + (16-sum_odd)*sum_even);
|
||||
}
|
||||
|
||||
|
||||
void TestSumProperty()
|
||||
{
|
||||
uint32_t statistics[257];
|
||||
struct Crypto1State cs;
|
||||
|
||||
for (uint16_t i = 0; i < 257; i++) {
|
||||
statistics[i] = 0;
|
||||
}
|
||||
time_t time1 = clock();
|
||||
|
||||
#define NUM_STATISTICS 1000000
|
||||
for (uint32_t i = 0; i < NUM_STATISTICS; i++) {
|
||||
cs.odd = (rand() & 0xfff) << 12 | (rand() & 0xfff);
|
||||
cs.even = (rand() & 0xfff) << 12 | (rand() & 0xfff);
|
||||
uint16_t sum_property = SumProperty(&cs);
|
||||
statistics[sum_property] += 1;
|
||||
if (i%(NUM_STATISTICS/100) == 0) printf(".");
|
||||
}
|
||||
|
||||
printf("\nCalculated %d Sum properties in %0.3f seconds (%0.0f calcs/second)\n", NUM_STATISTICS, ((float)clock() - time1)/CLOCKS_PER_SEC, NUM_STATISTICS/((float)clock() - time1)*CLOCKS_PER_SEC);
|
||||
for (uint16_t i = 0; i < 257; i++) {
|
||||
if (statistics[i] != 0) {
|
||||
printf("probability[%3d] = %0.5f\n", i, (float)statistics[i]/NUM_STATISTICS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, bool nonce_file_read, bool nonce_file_write, bool slow)
|
||||
{
|
||||
UsbCommand resp;
|
||||
|
@ -202,13 +333,53 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
|
|||
uint32_t flags = 0;
|
||||
bool initialize = true;
|
||||
clock_t time1;
|
||||
uint8_t read_buf[9];
|
||||
uint32_t nt_enc1, nt_enc2;
|
||||
uint8_t par_enc;
|
||||
uint32_t cuid;
|
||||
|
||||
// initialize the list of nonces
|
||||
for (uint16_t i = 0; i < 256; i++) {
|
||||
nonces[i].num = 0;
|
||||
nonces[i].Sum = 0;
|
||||
nonces[i].first = NULL;
|
||||
}
|
||||
first_byte_num = 0;
|
||||
first_byte_Sum = 0;
|
||||
|
||||
//StateList_t statelists[2];
|
||||
//struct Crypto1State *p1, *p2, *p3, *p4;
|
||||
|
||||
if (nonce_file_read) {
|
||||
// don't acquire nonces, use pre-acquired data from file nonces.bin
|
||||
PrintAndLog("Reading nonces not yet implemented.");
|
||||
if ((fnonces = fopen("nonces.bin","rb")) == NULL) {
|
||||
PrintAndLog("Could not open file nonces.bin");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("Reading nonces from file nonces.bin...");
|
||||
if (fread(read_buf, 1, 6, fnonces) == 0) {
|
||||
PrintAndLog("File reading error.");
|
||||
fclose(fnonces);
|
||||
return 1;
|
||||
}
|
||||
cuid = bytes_to_num(read_buf, 4);
|
||||
trgBlockNo = bytes_to_num(read_buf+4, 1);
|
||||
trgKeyType = bytes_to_num(read_buf+5, 1);
|
||||
|
||||
while (!feof(fnonces)) {
|
||||
fread(read_buf, 1, 9, fnonces);
|
||||
nt_enc1 = bytes_to_num(read_buf, 4);
|
||||
nt_enc2 = bytes_to_num(read_buf+4, 4);
|
||||
par_enc = bytes_to_num(read_buf+8, 1);
|
||||
add_nonce(nt_enc1, par_enc >> 4);
|
||||
add_nonce(nt_enc2, par_enc & 0x0f);
|
||||
total_num_nonces += 2;
|
||||
}
|
||||
fclose(fnonces);
|
||||
PrintAndLog("Read %d nonces from file", total_num_nonces);
|
||||
|
||||
} else {
|
||||
|
||||
// acquire nonces.
|
||||
time1 = clock();
|
||||
do {
|
||||
|
@ -229,7 +400,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
|
|||
return resp.arg[0]; // error during nested
|
||||
}
|
||||
|
||||
uint32_t cuid = resp.arg[1];
|
||||
cuid = resp.arg[1];
|
||||
uint16_t num_acquired_nonces = resp.arg[2];
|
||||
|
||||
//PrintAndLog("Received %d nonces", num_acquired_nonces);
|
||||
|
@ -249,18 +420,24 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
|
|||
uint8_t par_enc;
|
||||
uint8_t *bufp = resp.d.asBytes;
|
||||
for (uint16_t i = 0; i < num_acquired_nonces/2; i++) {
|
||||
memcpy(&nt_enc1, bufp, sizeof(nt_enc1));
|
||||
nt_enc1 = bytes_to_num(bufp, sizeof(nt_enc1));
|
||||
bufp += sizeof(nt_enc1);
|
||||
memcpy(&nt_enc2, bufp, sizeof(nt_enc2));
|
||||
nt_enc2 = bytes_to_num(bufp, sizeof(nt_enc2));
|
||||
bufp += sizeof(nt_enc2);
|
||||
memcpy(&par_enc, bufp, sizeof(par_enc));
|
||||
par_enc = bytes_to_num(bufp, sizeof(par_enc));
|
||||
bufp += sizeof(par_enc);
|
||||
|
||||
add_nonce(nt_enc1, par_enc >> 4);
|
||||
add_nonce(nt_enc2, par_enc & 0x0f);
|
||||
|
||||
//printf("Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc1, par_enc >> 4);
|
||||
//printf("Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc2, par_enc & 0x0f);
|
||||
if (nonce_file_write) {
|
||||
fwrite(&nt_enc1, 1, sizeof(nt_enc1), fnonces);
|
||||
fwrite(&nt_enc2, 1, sizeof(nt_enc2), fnonces);
|
||||
fwrite(&par_enc, 1, sizeof(par_enc), fnonces);
|
||||
uint8_t buffer[9];
|
||||
num_to_bytes(nt_enc1, 4, buffer);
|
||||
num_to_bytes(nt_enc2, 4, buffer+4);
|
||||
num_to_bytes(par_enc, 1, buffer+8);
|
||||
fwrite(buffer, 1, 9, fnonces);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +452,11 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
|
|||
PrintAndLog("Acquired a total of %d nonces at a rate of %d nonces/minute", total_num_nonces, total_num_nonces*60*CLOCKS_PER_SEC/(clock() - time1));
|
||||
}
|
||||
|
||||
PrintAndLog("Attack not yet implemented");
|
||||
PrintAndLog("first_byte_num: %d, first_byte_Sum: %d", first_byte_num, first_byte_Sum);
|
||||
|
||||
TestSumProperty();
|
||||
|
||||
PrintAndLog("Generation of candidate list and brute force phase not yet implemented");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue