mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
hitag2crack refactor
This commit is contained in:
@@ -85,14 +85,9 @@ unsigned char hex2bin(unsigned char c) {
|
||||
|
||||
// return a single bit from a value
|
||||
int bitn(uint64_t x, int bit) {
|
||||
uint64_t bitmask = 1;
|
||||
bitmask <<= bit;
|
||||
const uint64_t bitmask = (uint64_t)(1) << bit;
|
||||
|
||||
if (x & bitmask) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (x & bitmask) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,17 +121,15 @@ int fc(unsigned int i) {
|
||||
|
||||
// the filter function that generates a bit of output from the prng state
|
||||
int fnf(uint64_t s) {
|
||||
unsigned int x1, x2, x3, x4, x5, x6;
|
||||
const unsigned int x1 = (unsigned int)((bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3));
|
||||
const unsigned int x2 = (unsigned int)((bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3));
|
||||
const unsigned int x3 = (unsigned int)((bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3));
|
||||
const unsigned int x4 = (unsigned int)((bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3));
|
||||
const unsigned int x5 = (unsigned int)((bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3));
|
||||
|
||||
x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3);
|
||||
x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3);
|
||||
x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3);
|
||||
x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3);
|
||||
x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3);
|
||||
const unsigned int x6 = (unsigned int)((fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4));
|
||||
|
||||
x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4);
|
||||
|
||||
return fc(x6);
|
||||
return bitn(0x7907287B, (int) x6);
|
||||
}
|
||||
|
||||
// builds the lfsr for the prng (quick calcs for hitag2_nstep())
|
||||
@@ -151,9 +144,9 @@ void buildlfsr(Hitag_State *hstate) {
|
||||
^ (temp >> 42) ^ (temp >> 46);
|
||||
}
|
||||
|
||||
// convert byte-reversed 8 digit hex to unsigned long
|
||||
unsigned long hexreversetoulong(char *hex) {
|
||||
unsigned long ret = 0L;
|
||||
// convert byte-reversed 8 digit hex to uint32_t
|
||||
uint32_t hexreversetouint32(char *hex) {
|
||||
uint32_t ret = 0;
|
||||
unsigned int x;
|
||||
char i;
|
||||
|
||||
@@ -164,14 +157,14 @@ unsigned long hexreversetoulong(char *hex) {
|
||||
if (sscanf(hex, "%2X", &x) != 1) {
|
||||
return 0L;
|
||||
}
|
||||
ret += ((unsigned long) x) << i * 8;
|
||||
ret += ((uint32_t) x) << i * 8;
|
||||
hex += 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convert byte-reversed 12 digit hex to unsigned long
|
||||
unsigned long long hexreversetoulonglong(char *hex) {
|
||||
// convert byte-reversed 12 digit hex to uint64_t
|
||||
uint64_t hexreversetouint64(char *hex) {
|
||||
char tmp[9];
|
||||
|
||||
// this may seem an odd way to do it, but weird compiler issues were
|
||||
@@ -180,9 +173,9 @@ unsigned long long hexreversetoulonglong(char *hex) {
|
||||
tmp[8] = '\0';
|
||||
memset(tmp + 4, '0', 4);
|
||||
memcpy(tmp, hex + 8, 4);
|
||||
unsigned long long ret = hexreversetoulong(tmp);
|
||||
uint64_t ret = hexreversetouint32(tmp);
|
||||
ret <<= 32;
|
||||
memcpy(tmp, hex, 8);
|
||||
ret += hexreversetoulong(tmp);
|
||||
ret += hexreversetouint32(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ void buildlfsr(Hitag_State *hstate);
|
||||
#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8))
|
||||
#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16))
|
||||
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
|
||||
unsigned long hexreversetoulong(char *hex);
|
||||
unsigned long long hexreversetoulonglong(char *hex);
|
||||
uint32_t hexreversetouint32(char *hex);
|
||||
uint64_t hexreversetouint64(char *hex);
|
||||
|
||||
#endif /* HT2CRACKUTILS_H */
|
||||
|
||||
@@ -76,7 +76,7 @@ int main(int argc, char *argv[]) {
|
||||
hstate.shiftreg = 0;
|
||||
hstate.lfsr = 0;
|
||||
|
||||
hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nR)));
|
||||
hitag2_init(&hstate, rev64(hexreversetouint64(key)), rev32(hexreversetouint32(uid)), rev32(hexreversetouint32(nR)));
|
||||
|
||||
hitag2_nstep(&hstate, 64);
|
||||
|
||||
|
||||
@@ -314,8 +314,8 @@ static uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) {
|
||||
// key lower 16 bits are lower 16 bits of prng state
|
||||
key = hstate->shiftreg & 0xffff;
|
||||
nRxork = (hstate->shiftreg >> 16) & 0xffffffff;
|
||||
uid = rev32(hexreversetoulong(uidstr));
|
||||
nRenc = rev32(hexreversetoulong(nRstr));
|
||||
uid = rev32(hexreversetouint32(uidstr));
|
||||
nRenc = rev32(hexreversetouint32(nRstr));
|
||||
|
||||
uidtmp = uid;
|
||||
// rollback and extract bits b
|
||||
|
||||
@@ -376,8 +376,8 @@ static uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) {
|
||||
// key lower 16 bits are lower 16 bits of prng state
|
||||
key = hstate->shiftreg & 0xffff;
|
||||
nRxork = (hstate->shiftreg >> 16) & 0xffffffff;
|
||||
uid = rev32(hexreversetoulong(uidstr));
|
||||
nRenc = rev32(hexreversetoulong(nRstr));
|
||||
uid = rev32(hexreversetouint32(uidstr));
|
||||
nRenc = rev32(hexreversetouint32(nRstr));
|
||||
|
||||
uidtmp = uid;
|
||||
// rollback and extract bits b
|
||||
|
||||
@@ -308,9 +308,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// read the UID into internal format
|
||||
if (!strncmp(argv[1], "0x", 2)) {
|
||||
uid = rev32(hexreversetoulong(argv[1] + 2));
|
||||
uid = rev32(hexreversetouint32(argv[1] + 2));
|
||||
} else {
|
||||
uid = rev32(hexreversetoulong(argv[1]));
|
||||
uid = rev32(hexreversetouint32(argv[1]));
|
||||
}
|
||||
|
||||
// create table of nR aR pairs
|
||||
@@ -353,11 +353,11 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
*buft2 = 0x00;
|
||||
if (!strncmp(buf, "0x", 2)) {
|
||||
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf + 2));
|
||||
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1 + 2));
|
||||
TnRaR[numnrar].nR = rev32(hexreversetouint32(buf + 2));
|
||||
TnRaR[numnrar].aR = rev32(hexreversetouint32(buft1 + 2));
|
||||
} else {
|
||||
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf));
|
||||
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1));
|
||||
TnRaR[numnrar].nR = rev32(hexreversetouint32(buf));
|
||||
TnRaR[numnrar].aR = rev32(hexreversetouint32(buft1));
|
||||
}
|
||||
numnrar++;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
nr = line;
|
||||
}
|
||||
hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nr)));
|
||||
hitag2_init(&hstate, rev64(hexreversetouint64(key)), rev32(hexreversetouint32(uid)), rev32(hexreversetouint32(nr)));
|
||||
|
||||
arval = strtol(ar, NULL, 16);
|
||||
ks = hitag2_nstep(&hstate, 32);
|
||||
|
||||
@@ -251,9 +251,9 @@ static void init_guess_table(char *filename, char *uidstr) {
|
||||
|
||||
// read uid
|
||||
if (!strncmp(uidstr, "0x", 2)) {
|
||||
uid = rev32(hexreversetoulong(uidstr + 2));
|
||||
uid = rev32(hexreversetouint32(uidstr + 2));
|
||||
} else {
|
||||
uid = rev32(hexreversetoulong(uidstr));
|
||||
uid = rev32(hexreversetouint32(uidstr));
|
||||
}
|
||||
|
||||
|
||||
@@ -286,11 +286,11 @@ static void init_guess_table(char *filename, char *uidstr) {
|
||||
}
|
||||
*buft2 = 0x00;
|
||||
if (!strncmp(buf, "0x", 2)) {
|
||||
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf + 2));
|
||||
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1 + 2)) ^ 0xffffffff;
|
||||
nonces[num_nRaR].enc_nR = rev32(hexreversetouint32(buf + 2));
|
||||
nonces[num_nRaR].ks = rev32(hexreversetouint32(buft1 + 2)) ^ 0xffffffff;
|
||||
} else {
|
||||
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf));
|
||||
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff;
|
||||
nonces[num_nRaR].enc_nR = rev32(hexreversetouint32(buf));
|
||||
nonces[num_nRaR].ks = rev32(hexreversetouint32(buft1)) ^ 0xffffffff;
|
||||
}
|
||||
num_nRaR++;
|
||||
}
|
||||
@@ -797,7 +797,7 @@ int main(int argc, char *argv[]) {
|
||||
maxtablesize = atoi(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
supplied_testkey = rev64(hexreversetoulonglong(optarg));
|
||||
supplied_testkey = rev64(hexreversetouint64(optarg));
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
|
||||
@@ -138,23 +138,23 @@ int main(int argc, char *argv[]) {
|
||||
thread_count = num_CPUs();
|
||||
|
||||
if (!strncmp(argv[1], "0x", 2) || !strncmp(argv[1], "0X", 2)) {
|
||||
uid = rev32(hexreversetoulong(argv[1] + 2));
|
||||
uid = rev32(hexreversetouint32(argv[1] + 2));
|
||||
} else {
|
||||
uid = rev32(hexreversetoulong(argv[1]));
|
||||
uid = rev32(hexreversetouint32(argv[1]));
|
||||
}
|
||||
|
||||
if (!strncmp(argv[2], "0x", 2) || !strncmp(argv[2], "0X", 2)) {
|
||||
nR1 = rev32(hexreversetoulong(argv[2] + 2));
|
||||
nR1 = rev32(hexreversetouint32(argv[2] + 2));
|
||||
} else {
|
||||
nR1 = rev32(hexreversetoulong(argv[2]));
|
||||
nR1 = rev32(hexreversetouint32(argv[2]));
|
||||
}
|
||||
|
||||
aR1 = strtol(argv[3], NULL, 16);
|
||||
|
||||
if (!strncmp(argv[4], "0x", 2) || !strncmp(argv[4], "0X", 2)) {
|
||||
nR2 = rev32(hexreversetoulong(argv[4] + 2));
|
||||
nR2 = rev32(hexreversetouint32(argv[4] + 2));
|
||||
} else {
|
||||
nR2 = rev32(hexreversetoulong(argv[4]));
|
||||
nR2 = rev32(hexreversetouint32(argv[4]));
|
||||
}
|
||||
|
||||
aR2 = strtol(argv[5], NULL, 16);
|
||||
|
||||
@@ -190,23 +190,23 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (!strncmp(argv[1], "0x", 2) || !strncmp(argv[1], "0X", 2)) {
|
||||
uid = rev32(hexreversetoulong(argv[1] + 2));
|
||||
uid = rev32(hexreversetouint32(argv[1] + 2));
|
||||
} else {
|
||||
uid = rev32(hexreversetoulong(argv[1]));
|
||||
uid = rev32(hexreversetouint32(argv[1]));
|
||||
}
|
||||
|
||||
if (!strncmp(argv[2], "0x", 2) || !strncmp(argv[2], "0X", 2)) {
|
||||
nR1 = rev32(hexreversetoulong(argv[2] + 2));
|
||||
nR1 = rev32(hexreversetouint32(argv[2] + 2));
|
||||
} else {
|
||||
nR1 = rev32(hexreversetoulong(argv[2]));
|
||||
nR1 = rev32(hexreversetouint32(argv[2]));
|
||||
}
|
||||
|
||||
aR1 = strtol(argv[3], NULL, 16);
|
||||
|
||||
if (!strncmp(argv[4], "0x", 2) || !strncmp(argv[4], "0X", 2)) {
|
||||
nR2 = rev32(hexreversetoulong(argv[4] + 2));
|
||||
nR2 = rev32(hexreversetouint32(argv[4] + 2));
|
||||
} else {
|
||||
nR2 = rev32(hexreversetoulong(argv[4]));
|
||||
nR2 = rev32(hexreversetouint32(argv[4]));
|
||||
}
|
||||
|
||||
aR2 = strtol(argv[5], NULL, 16);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
MYSRCS = queue.c threads.c opencl.c hitag2.c
|
||||
MYSRCPATHS = ../common
|
||||
MYSRCS = queue.c threads.c opencl.c hitag2.c ht2crackutils.c hitagcrypto.c
|
||||
MYINCLUDES =-I ../common
|
||||
MYCFLAGS =
|
||||
MYDEFS = -D TEST_UNIT=0
|
||||
|
||||
|
||||
@@ -1,48 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include "ht2crack5opencl.h"
|
||||
#include "hitagcrypto.h"
|
||||
#include "ht2crackutils.h"
|
||||
#include "hitag2.h"
|
||||
|
||||
//#if FORCE_HITAG2_FULL == 0
|
||||
|
||||
// return a single bit from a value
|
||||
int bitn(uint64_t x, int bit) {
|
||||
const uint64_t bitmask = (uint64_t)(1) << bit;
|
||||
|
||||
return (x & bitmask) ? 1 : 0;
|
||||
}
|
||||
|
||||
// the sub-function R that rollback depends upon
|
||||
int fnR(uint64_t x) {
|
||||
// renumbered bits because my state is 0-47, not 1-48
|
||||
return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^
|
||||
bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 15) ^
|
||||
bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^
|
||||
bitn(x, 29) ^ bitn(x, 40) ^ bitn(x, 41) ^
|
||||
bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
|
||||
}
|
||||
|
||||
// the three filter sub-functions that feed fnf
|
||||
int fa(unsigned int i) {
|
||||
return bitn(0x2C79, (int)i);
|
||||
}
|
||||
|
||||
int fb(unsigned int i) {
|
||||
return bitn(0x6671, (int)i);
|
||||
}
|
||||
|
||||
// the filter function that generates a bit of output from the prng state
|
||||
int fnf(uint64_t s) {
|
||||
const unsigned int x1 = (unsigned int)((bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3));
|
||||
const unsigned int x2 = (unsigned int)((bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3));
|
||||
const unsigned int x3 = (unsigned int)((bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3));
|
||||
const unsigned int x4 = (unsigned int)((bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3));
|
||||
const unsigned int x5 = (unsigned int)((bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3));
|
||||
|
||||
const unsigned int x6 = (unsigned int)((fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4));
|
||||
|
||||
return bitn(0x7907287B, (int) x6);
|
||||
}
|
||||
|
||||
uint32_t hitag2_crypt(uint64_t x) {
|
||||
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
|
||||
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
|
||||
@@ -63,123 +26,6 @@ uint32_t hitag2_crypt(uint64_t x) {
|
||||
return (ht2_function5c >> bitindex) & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return up to 32 crypto bits.
|
||||
* Last bit is in least significant bit, earlier bits are shifted left.
|
||||
* Note that the Hitag transmission protocol is least significant bit,
|
||||
* so we may want to change this, or add a function, that returns the
|
||||
* crypto output bits in the other order.
|
||||
*
|
||||
* Parameters:
|
||||
* Hitag_State* pstate - in/out, internal cipher state after initialisation
|
||||
* uint32_t steps - number of bits requested, (capped at 32)
|
||||
*/
|
||||
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) {
|
||||
uint64_t cur_state = pstate->shiftreg;
|
||||
uint32_t result = 0;
|
||||
uint64_t lfsr = pstate->lfsr;
|
||||
|
||||
if (steps == 0) return 0;
|
||||
|
||||
do {
|
||||
// update shift registers
|
||||
if (lfsr & 1) {
|
||||
cur_state = (cur_state >> 1) | 0x800000000000;
|
||||
lfsr = (lfsr >> 1) ^ 0xB38083220073;
|
||||
|
||||
// accumulate next bit of crypto
|
||||
result = (result << 1) | hitag2_crypt(cur_state);
|
||||
} else {
|
||||
cur_state >>= 1;
|
||||
lfsr >>= 1;
|
||||
|
||||
result = (result << 1) | hitag2_crypt(cur_state);
|
||||
}
|
||||
} while (--steps);
|
||||
|
||||
#if defined(DEBUG_HITAG2) && DEBUG_HITAG2 == 1
|
||||
#ifdef _ISOC99_SOURCE
|
||||
printf("hitag2_nstep cur_state = %012I64x, result %02x\n", cur_state, result);
|
||||
#else
|
||||
printf("hitag2_nstep cur_state = %012" STR(OFF_FORMAT_X) ", result %02x\n", cur_state, result);
|
||||
#endif
|
||||
#endif // DEBUG_HITAG2
|
||||
|
||||
pstate->shiftreg = cur_state;
|
||||
pstate->lfsr = lfsr;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parameters:
|
||||
* Hitag_State* pstate - output, internal state after initialisation
|
||||
* uint64_t sharedkey - 48 bit key shared between reader & tag
|
||||
* uint32_t serialnum - 32 bit tag serial number
|
||||
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
|
||||
*/
|
||||
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) {
|
||||
// init state, from serial number and lowest 16 bits of shared key
|
||||
uint64_t cur_state = ((sharedkey & 0xFFFF) << 32) | serialnum;
|
||||
|
||||
// mix the initialisation vector and highest 32 bits of the shared key
|
||||
initvector ^= (uint32_t)(sharedkey >> 16);
|
||||
|
||||
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
|
||||
// these will be XORed in turn with output of the crypto function
|
||||
cur_state |= (uint64_t) initvector << 48;
|
||||
initvector >>= 16;
|
||||
|
||||
// unrolled loop is faster on PIC32 (MIPS), do 32 times
|
||||
// shift register, then calc new bit
|
||||
cur_state >>= 1;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46;
|
||||
}
|
||||
|
||||
// highest 16 bits of IV XOR Shared Key
|
||||
cur_state |= (uint64_t) initvector << 47;
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46;
|
||||
}
|
||||
|
||||
cur_state ^= (uint64_t) hitag2_crypt(cur_state) << 47;
|
||||
|
||||
pstate->shiftreg = cur_state;
|
||||
#if defined(DEBUG_HITAG2) && DEBUG_HITAG2 == 1
|
||||
#ifdef _ISOC99_SOURCE
|
||||
printf("hitag2_init shiftreg = %012I64x\n", pstate->shiftreg);
|
||||
#else
|
||||
printf("hitag2_init shiftreg = %012" STR(OFF_FORMAT_X) "\n", pstate->shiftreg);
|
||||
#endif
|
||||
#endif // DEBUG_HITAG2
|
||||
|
||||
/* naive version for reference, LFSR has 16 taps
|
||||
pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6)
|
||||
^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22)
|
||||
^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
|
||||
^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47);
|
||||
*/
|
||||
|
||||
// optimise with one 64-bit intermediate
|
||||
uint64_t temp = cur_state ^ (cur_state >> 1);
|
||||
|
||||
pstate->lfsr = cur_state ^ (cur_state >> 6) ^ (cur_state >> 16) ^
|
||||
(cur_state >> 26) ^ (cur_state >> 30) ^ (cur_state >> 41) ^
|
||||
(temp >> 2) ^ (temp >> 7) ^ (temp >> 22) ^ (temp >> 42) ^ (temp >> 46);
|
||||
|
||||
#if defined(DEBUG_HITAG2) && DEBUG_HITAG2 == 1
|
||||
#ifdef _ISOC99_SOURCE
|
||||
printf("hitag2_init lfsr = %012I64x\n", pstate->lfsr);
|
||||
#else
|
||||
printf("hitag2_init lfsr = %012" STR(OFF_FORMAT_X) "\n", pstate->lfsr);
|
||||
#endif
|
||||
#endif // DEBUG_HITAG2
|
||||
}
|
||||
|
||||
// try state
|
||||
|
||||
// todo, changes arguments, only what is needed
|
||||
|
||||
@@ -27,25 +27,6 @@
|
||||
#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16))
|
||||
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
|
||||
|
||||
typedef struct {
|
||||
uint64_t shiftreg; // naive shift register, required for nonlinear fn input
|
||||
uint64_t lfsr; // fast lfsr, used to make software faster
|
||||
} Hitag_State;
|
||||
|
||||
// return a single bit from a value
|
||||
int bitn(uint64_t x, int bit);
|
||||
|
||||
// the sub-function R that rollback depends upon
|
||||
int fnR(uint64_t x);
|
||||
|
||||
// the three filter sub-functions that feed fnf
|
||||
int fa(unsigned int i);
|
||||
|
||||
int fb(unsigned int i);
|
||||
|
||||
// the filter function that generates a bit of output from the prng state
|
||||
int fnf(uint64_t s);
|
||||
|
||||
// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
|
||||
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
|
||||
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
|
||||
@@ -55,28 +36,6 @@ int fnf(uint64_t s);
|
||||
|
||||
uint32_t hitag2_crypt(uint64_t x);
|
||||
|
||||
/*
|
||||
* Return up to 32 crypto bits.
|
||||
* Last bit is in least significant bit, earlier bits are shifted left.
|
||||
* Note that the Hitag transmission protocol is least significant bit,
|
||||
* so we may want to change this, or add a function, that returns the
|
||||
* crypto output bits in the other order.
|
||||
*
|
||||
* Parameters:
|
||||
* Hitag_State* pstate - in/out, internal cipher state after initialisation
|
||||
* uint32_t steps - number of bits requested, (capped at 32)
|
||||
*/
|
||||
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps);
|
||||
|
||||
/*
|
||||
* Parameters:
|
||||
* Hitag_State* pstate - output, internal state after initialisation
|
||||
* uint64_t sharedkey - 48 bit key shared between reader & tag
|
||||
* uint32_t serialnum - 32 bit tag serial number
|
||||
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
|
||||
*/
|
||||
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
|
||||
|
||||
// try_state
|
||||
bool try_state(uint64_t s, uint32_t uid, uint32_t aR2, uint32_t nR1, uint32_t nR2, uint64_t *key);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "ht2crackutils.h"
|
||||
#include "ht2crack5opencl.h"
|
||||
#include "queue.h"
|
||||
#include "threads.h"
|
||||
@@ -35,7 +36,6 @@
|
||||
#include "hitag2.h"
|
||||
#include "dolphin_macro.h"
|
||||
|
||||
|
||||
#define AEND "\x1b[0m"
|
||||
#define _RED_(s) "\x1b[31m" s AEND
|
||||
#define _GREEN_(s) "\x1b[32m" s AEND
|
||||
@@ -110,24 +110,6 @@ static void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value)
|
||||
}
|
||||
}
|
||||
|
||||
// convert byte-reversed 8 digit hex to unsigned long
|
||||
static unsigned long hexreversetoulong(char *hex) {
|
||||
unsigned long ret = 0L;
|
||||
unsigned int x;
|
||||
char i;
|
||||
|
||||
if (strlen(hex) != 8)
|
||||
return 0L;
|
||||
|
||||
for (i = 0 ; i < 4 ; ++i) {
|
||||
if (sscanf(hex, "%2X", &x) != 1)
|
||||
return 0L;
|
||||
ret += ((unsigned long) x) << i * 8;
|
||||
hex += 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_EMOJ == 1
|
||||
static const char *emoj[3][2] = { {"∩", "つ"}, {"つ", "⊃"}, {"⊃", "੭ " } };
|
||||
#endif
|
||||
@@ -346,13 +328,13 @@ int main(int argc, char **argv) {
|
||||
printf("Error: invalid UID length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
uid = (uint32_t) rev32(hexreversetoulong(argv[optind] + 2));
|
||||
uid = (uint32_t) rev32(hexreversetouint32(argv[optind] + 2));
|
||||
} else {
|
||||
if (strlen(argv[optind]) != 8) {
|
||||
printf("Error: invalid UID length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
uid = (uint32_t) rev32(hexreversetoulong(argv[optind]));
|
||||
uid = (uint32_t) rev32(hexreversetouint32(argv[optind]));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -362,13 +344,13 @@ int main(int argc, char **argv) {
|
||||
printf("Error: invalid nR1 length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
nR1 = (uint32_t) rev32(hexreversetoulong(argv[optind] + 2));
|
||||
nR1 = (uint32_t) rev32(hexreversetouint32(argv[optind] + 2));
|
||||
} else {
|
||||
if (strlen(argv[optind]) != 8) {
|
||||
printf("Error: invalid nR1 length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
nR1 = (uint32_t) rev32(hexreversetoulong(argv[optind]));
|
||||
nR1 = (uint32_t) rev32(hexreversetouint32(argv[optind]));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -386,13 +368,13 @@ int main(int argc, char **argv) {
|
||||
printf("Error: invalid nR2 length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
nR2 = (uint32_t) rev32(hexreversetoulong(argv[optind] + 2));
|
||||
nR2 = (uint32_t) rev32(hexreversetouint32(argv[optind] + 2));
|
||||
} else {
|
||||
if (strlen(argv[optind]) != 8) {
|
||||
printf("Error: invalid nR2 length\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
nR2 = (uint32_t) rev32(hexreversetoulong(argv[optind]));
|
||||
nR2 = (uint32_t) rev32(hexreversetouint32(argv[optind]));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user