mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-15 22:29:52 +08:00
Added hf iclass unhash
Added hf iclass unhash based on the document "Exposing iClass Key Diversification" The command works but only handles the "main" scenarios, retrieving only 8/512 potential hash0 pre-images. Handling of the additional pre-images is still work in progress.
This commit is contained in:
parent
7be8ee0c69
commit
d5469d567f
4 changed files with 291 additions and 20 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added `hf iclass unhash` command to reverse an iclass diversified key to hash0 pre-images (@antiklesys)
|
||||||
- Added crypto1 support to `hf 14a raw` (@doegox)
|
- Added crypto1 support to `hf 14a raw` (@doegox)
|
||||||
- Changed `hw version` command to print LUA and Python versions (@jmichelp)
|
- Changed `hw version` command to print LUA and Python versions (@jmichelp)
|
||||||
- Updated LUA to v5.4.7 which adds utf-8 support (@jmichelp)
|
- Updated LUA to v5.4.7 which adds utf-8 support (@jmichelp)
|
||||||
|
|
|
@ -4123,7 +4123,7 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
HFiClassCalcDivKey(csn, iClass_Key_Table[1], new_div_key, false);
|
diversifyKey(csn, iClass_Key_Table[1], new_div_key);
|
||||||
memcpy(no_first_auth,new_div_key,PICOPASS_BLOCK_SIZE);
|
memcpy(no_first_auth,new_div_key,PICOPASS_BLOCK_SIZE);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
@ -4142,6 +4142,40 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHFiClassUnhash(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf iclass unhash",
|
||||||
|
"Reverses the hash0 function used generate iclass diversified keys after DES encryption, returning the DES crypted CSN.",
|
||||||
|
"hf iclass unhash --divkey B4F12AADC5301A2D"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str1(NULL, "divkey", "<hex>", "The card's Diversified Key value"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
int dk_len = 0;
|
||||||
|
uint8_t div_key[PICOPASS_BLOCK_SIZE] = {0};
|
||||||
|
CLIGetHexWithReturn(ctx, 1, div_key, &dk_len);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (dk_len && dk_len != PICOPASS_BLOCK_SIZE) {
|
||||||
|
PrintAndLogEx(ERR, "Diversified Key is incorrect length");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, _YELLOW_("Div Key: ")"%s", sprint_hex(div_key, sizeof(div_key)));
|
||||||
|
|
||||||
|
invert_hash0(div_key);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHFiClassLookUp(const char *Cmd) {
|
static int CmdHFiClassLookUp(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf iclass lookup",
|
CLIParserInit(&ctx, "hf iclass lookup",
|
||||||
|
@ -5070,8 +5104,9 @@ static command_t CommandTable[] = {
|
||||||
{"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "Check keys"},
|
{"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "Check keys"},
|
||||||
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "Use loclass to perform bruteforce reader attack"},
|
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "Use loclass to perform bruteforce reader attack"},
|
||||||
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "Uses authentication trace to check for key in dictionary file"},
|
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "Uses authentication trace to check for key in dictionary file"},
|
||||||
{"legrec", CmdHFiClassLegacyRecover, IfPm3Iclass, "Attempts to recover the standard key of a legacy card"},
|
{"legrec", CmdHFiClassLegacyRecover, IfPm3Iclass, "Recovers 24 bits of the diversified key of a legacy card provided a valid nr-mac combination"},
|
||||||
{"legbrute", CmdHFiClassLegRecLookUp, AlwaysAvailable, "Bruteforces 40 bits of a partial raw key"},
|
{"legbrute", CmdHFiClassLegRecLookUp, AlwaysAvailable, "Bruteforces 40 bits of a partial diversified key, provided 24 bits of the key and two valid nr-macs"},
|
||||||
|
{"unhash", CmdHFiClassUnhash, AlwaysAvailable, "Reverses a diversified key to retrieve hash0 pre-images after DES encryption"},
|
||||||
{"-----------", CmdHelp, IfPm3Iclass, "-------------------- " _CYAN_("Simulation") " -------------------"},
|
{"-----------", CmdHelp, IfPm3Iclass, "-------------------- " _CYAN_("Simulation") " -------------------"},
|
||||||
{"sim", CmdHFiClassSim, IfPm3Iclass, "Simulate iCLASS tag"},
|
{"sim", CmdHFiClassSim, IfPm3Iclass, "Simulate iCLASS tag"},
|
||||||
{"eload", CmdHFiClassELoad, IfPm3Iclass, "Upload file into emulator memory"},
|
{"eload", CmdHFiClassELoad, IfPm3Iclass, "Upload file into emulator memory"},
|
||||||
|
|
|
@ -154,8 +154,7 @@ static uint64_t ck(int i, int j, uint64_t z) {
|
||||||
if (getSixBitByte(z, i) == getSixBitByte(z, j)) {
|
if (getSixBitByte(z, i) == getSixBitByte(z, j)) {
|
||||||
//ck(i, j − 1, z [0] . . . z [i] ← j . . . z [3] )
|
//ck(i, j − 1, z [0] . . . z [i] ← j . . . z [3] )
|
||||||
uint64_t newz = 0;
|
uint64_t newz = 0;
|
||||||
int c;
|
for (int c = 0; c < 4; c++) {
|
||||||
for (c = 0; c < 4; c++) {
|
|
||||||
uint8_t val = getSixBitByte(z, c);
|
uint8_t val = getSixBitByte(z, c);
|
||||||
if (c == i)
|
if (c == i)
|
||||||
pushbackSixBitByte(&newz, j, c);
|
pushbackSixBitByte(&newz, j, c);
|
||||||
|
@ -201,22 +200,51 @@ static uint64_t check(uint64_t z) {
|
||||||
return ck1 | ck2 >> 24;
|
return ck1 | ck2 >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void permute(BitstreamIn_t *p_in, uint64_t z, int l, int r, BitstreamOut_t *out) {
|
// Reverse ck (scramble-1)
|
||||||
if (bitsLeft(p_in) == 0)
|
static uint64_t reverse_ck(int i, int j, uint64_t z) {
|
||||||
return;
|
if (i == 1 && j == -1) {
|
||||||
|
return z;
|
||||||
bool pn = tailBit(p_in);
|
} else if (j == -1) {
|
||||||
if (pn) {
|
return reverse_ck(i - 1, i - 2, z);
|
||||||
// pn = 1
|
|
||||||
uint8_t zl = getSixBitByte(z, l);
|
|
||||||
push6bits(out, zl + 1);
|
|
||||||
permute(p_in, z, l + 1, r, out);
|
|
||||||
} else {
|
|
||||||
// otherwise
|
|
||||||
uint8_t zr = getSixBitByte(z, r);
|
|
||||||
push6bits(out, zr);
|
|
||||||
permute(p_in, z, l, r + 1, out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t newz = 0;
|
||||||
|
if (getSixBitByte(z, i) == j) { // Reverse the swap logic based on condition in scramble^{-1}
|
||||||
|
// Perform reverse swap
|
||||||
|
for (int c = 0; c < 4; c++) {
|
||||||
|
uint8_t val = getSixBitByte(z, c);
|
||||||
|
if (c == i) {
|
||||||
|
pushbackSixBitByte(&newz, getSixBitByte(z, j), c);
|
||||||
|
} else {
|
||||||
|
pushbackSixBitByte(&newz, val, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reverse_ck(i, j - 1, newz);
|
||||||
|
} else {
|
||||||
|
// Continue recursion
|
||||||
|
return reverse_ck(i, j - 1, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t reverse_check(uint64_t z) {
|
||||||
|
|
||||||
|
//retrieve ck1 and ck2 from the hash
|
||||||
|
|
||||||
|
// Step 1: Extract ck2 shifted part from result
|
||||||
|
// Assuming ck2 shifted part is from bits 0-23 of the result
|
||||||
|
uint64_t shifted_ck2_part = z & 0x0000000000FFFFFF; // Mask the lower 24 bits
|
||||||
|
|
||||||
|
// Step 2: Reconstruct ck2
|
||||||
|
uint64_t ck2 = shifted_ck2_part << 24; // Shift back to get original ck2 value
|
||||||
|
// Step 3: Recover ck1
|
||||||
|
uint64_t ck1 = z & ~(ck2 >> 24); // Clear the bits where ck2 affected the result
|
||||||
|
// Now ck1 and ck2 have their original values before (after ck function took place)
|
||||||
|
|
||||||
|
ck1 = reverse_ck(3,2,ck1);
|
||||||
|
ck2 = reverse_ck(3,2,ck2);
|
||||||
|
|
||||||
|
return ck1 | ck2 >> 24; //This is now zP
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printState(const char *desc, uint64_t c) {
|
static void printState(const char *desc, uint64_t c) {
|
||||||
|
@ -237,6 +265,43 @@ static void printState(const char *desc, uint64_t c) {
|
||||||
PrintAndLogEx(DEBUG, "%s", s);
|
PrintAndLogEx(DEBUG, "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void permute(BitstreamIn_t *p_in, uint64_t z, int l, int r, BitstreamOut_t *out) {
|
||||||
|
if (bitsLeft(p_in) == 0)
|
||||||
|
return;
|
||||||
|
bool pn = tailBit(p_in);
|
||||||
|
if (pn) {
|
||||||
|
// pn = 1
|
||||||
|
uint8_t zl = getSixBitByte(z, l);
|
||||||
|
push6bits(out, zl + 1);
|
||||||
|
permute(p_in, z, l + 1, r, out);
|
||||||
|
} else {
|
||||||
|
// otherwise
|
||||||
|
uint8_t zr = getSixBitByte(z, r);
|
||||||
|
push6bits(out, zr);
|
||||||
|
permute(p_in, z, l, r + 1, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reverse_permute(BitstreamIn_t *p_in, uint64_t z, int l, BitstreamOut_t *out1, BitstreamOut_t *out2, bool fix) {
|
||||||
|
if (bitsLeft(p_in) == 0)
|
||||||
|
return;
|
||||||
|
bool pn = tailBit(p_in);
|
||||||
|
if (pn) { //if p == 1 for that six bit position, then sum it
|
||||||
|
// pn = 1
|
||||||
|
uint8_t zl = getSixBitByte(z, l);
|
||||||
|
if(fix){
|
||||||
|
push6bits(out1, zl - 1);
|
||||||
|
}else{
|
||||||
|
push6bits(out1, zl );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise
|
||||||
|
uint8_t zr = getSixBitByte(z, l);
|
||||||
|
push6bits(out2, zr);
|
||||||
|
}
|
||||||
|
reverse_permute(p_in, z, l + 1, out1, out2, fix);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as
|
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as
|
||||||
|
@ -339,6 +404,175 @@ void hash0(uint64_t c, uint8_t k[8]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int find_p_in_pi(uint8_t p) {
|
||||||
|
for (int i = 0; i < 35; i++) {
|
||||||
|
if (pi[i] == p) {
|
||||||
|
return i; // Value found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // Value not found
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reverse hash0
|
||||||
|
void invert_hash0(uint8_t k[8]) {
|
||||||
|
|
||||||
|
uint8_t y = 0;
|
||||||
|
uint64_t zTilde = 0;
|
||||||
|
uint8_t p = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
y |= ((k[i] & 0x80) >> (7 - i)); // Recover the bit of y from the leftmost bit of k[i]
|
||||||
|
pushbackSixBitByte(&zTilde, (k[i] & 0x7E) >> 1, i); // Recover the six bits of zTilde from the middle of k[i]
|
||||||
|
if(g_debugMode > 0)printState("z~", zTilde);
|
||||||
|
p |= ((k[i] & 0x01) << i);
|
||||||
|
}
|
||||||
|
if(g_debugMode > 0)PrintAndLogEx(INFO, " y : %02x", y); //value of y (recovered 1 byte of the pre-image)
|
||||||
|
//check if p is part of the array pi, if not invert it
|
||||||
|
if(g_debugMode > 0)PrintAndLogEx(INFO, " p : %02x", p); //value of p (at some point in the original hash0)
|
||||||
|
int remainder = find_p_in_pi(p);
|
||||||
|
if (remainder < 0){
|
||||||
|
p = ~p;
|
||||||
|
remainder = find_p_in_pi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_debugMode > 0)PrintAndLogEx(INFO, " p or ~p : %02x", p); //value of p (at some point in the original hash0)
|
||||||
|
|
||||||
|
//find possible values of x that can return the same remainder
|
||||||
|
uint8_t x_count = 0;
|
||||||
|
uint8_t x_array[8];
|
||||||
|
for (int x = 0x00; x <= 0xFF; x++) {
|
||||||
|
if(x % 35 == remainder){
|
||||||
|
x_array[x_count] = x;
|
||||||
|
x_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pre_image_base[8] = {0};
|
||||||
|
pre_image_base[1] = y;
|
||||||
|
//calculate pre-images based on the potential values of x (should we use pre-flip p and post flip p just in case?)
|
||||||
|
uint64_t zTil_img[8] = {0}; //8 is the max size it'll have as per max number of X pre-images
|
||||||
|
for(int img = 0; img < x_count; img++){ //for each potential value of x calculate a pre-image
|
||||||
|
zTil_img[img] = zTilde;
|
||||||
|
pre_image_base[0] = x_array[img];
|
||||||
|
uint8_t pc = p; //redefine and reassociate it here or it'll keep changing through the loops
|
||||||
|
if (x_array[img] & 1){ //Check if potential x7 is 1, if it is then invert p
|
||||||
|
pc = ~p;
|
||||||
|
}
|
||||||
|
//calculate zTilde for the x preimage
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
uint8_t p_i = (pc >> i) & 0x1; //this is correct!
|
||||||
|
uint8_t zTilde_i = getSixBitByte(zTilde, i) << 1;
|
||||||
|
if (k[i] & 0x80) { //this checks the value of the first bit of the byte (value of y_i)
|
||||||
|
if(p_i){
|
||||||
|
zTilde_i--;
|
||||||
|
}
|
||||||
|
zTilde_i = ~zTilde_i; //flip the 6 bit string
|
||||||
|
} else {
|
||||||
|
zTilde_i |= p_i & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushbackSixBitByte(&zTil_img[img], zTilde_i >> 1, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_debugMode > 0){
|
||||||
|
PrintAndLogEx(INFO, _YELLOW_("Testing Pre-Image Base: %s"), sprint_hex(pre_image_base, sizeof(pre_image_base)));
|
||||||
|
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
|
||||||
|
printState("0|0|z~", zTil_img[img]); //we retrieve the values of z~
|
||||||
|
PrintAndLogEx(INFO, " p or ~p : %02x", pc); //value of p (at some point in the original hash0)
|
||||||
|
}
|
||||||
|
//reverse permute
|
||||||
|
BitstreamIn_t p_in = { &pc, 8, 0 };
|
||||||
|
uint8_t outbuffer_1[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
uint8_t outbuffer_2[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
BitstreamOut_t out_1 = {outbuffer_1, 0, 0};
|
||||||
|
BitstreamOut_t out_2 = {outbuffer_2, 0, 0};
|
||||||
|
reverse_permute(&p_in, zTil_img[img], 0, &out_1, &out_2, false); //sort the bits
|
||||||
|
|
||||||
|
//Shift z-values down onto the lower segment
|
||||||
|
uint64_t zCaret_1 = x_bytes_to_num(outbuffer_1, sizeof(outbuffer_1));
|
||||||
|
zCaret_1 >>= 16;
|
||||||
|
uint64_t zCaret_2 = x_bytes_to_num(outbuffer_2, sizeof(outbuffer_2));
|
||||||
|
zCaret_2 >>= 40;
|
||||||
|
uint64_t zCaret = zCaret_1 | zCaret_2;
|
||||||
|
if (g_debugMode > 0) printState("0|0|z^", zCaret);
|
||||||
|
|
||||||
|
//fix the bits values
|
||||||
|
uint8_t p_fix = 0x0F; //fix bits mask as the bits will be in 11110000 order
|
||||||
|
BitstreamIn_t p_in_f = { &p_fix, 8, 0 };
|
||||||
|
uint8_t outbuffer_f1[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
uint8_t outbuffer_f2[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
BitstreamOut_t out_f1 = {outbuffer_f1, 0, 0};
|
||||||
|
BitstreamOut_t out_f2 = {outbuffer_f2, 0, 0};
|
||||||
|
reverse_permute(&p_in_f, zCaret, 0, &out_f1, &out_f2, true); //fixes the bits accordingly
|
||||||
|
|
||||||
|
//Shift z-values down onto the lower segment
|
||||||
|
uint64_t zCaret_fixed1 = x_bytes_to_num(outbuffer_f1, sizeof(outbuffer_f1));
|
||||||
|
zCaret_fixed1 >>= 16;
|
||||||
|
uint64_t zCaret_fixed2 = x_bytes_to_num(outbuffer_f2, sizeof(outbuffer_f2));
|
||||||
|
zCaret_fixed2 >>= 40;
|
||||||
|
|
||||||
|
uint64_t zCaret_fixed = zCaret_fixed1 | zCaret_fixed2;
|
||||||
|
if (g_debugMode > 0) printState("0|0|z^", zCaret_fixed);
|
||||||
|
|
||||||
|
uint64_t zP = reverse_check(zCaret_fixed);
|
||||||
|
if (g_debugMode > 0) printState("0|0|z'", zP);
|
||||||
|
|
||||||
|
//reverse the modulo transformation in the hash0 function for the six-bit chunks
|
||||||
|
|
||||||
|
uint64_t c = 0;
|
||||||
|
|
||||||
|
//Depending on their positions, values 3c, 3d, 3e, 3f can lead to additional pre-images.
|
||||||
|
//When these values are present we need to generate additional pre-images if they have the same modulo as other values
|
||||||
|
|
||||||
|
for (int n=0; n < 4; n++){
|
||||||
|
uint8_t _zn = getSixBitByte(zP, n); //handles the first 4 six-bit bytes
|
||||||
|
uint8_t _zn4 = getSixBitByte(zP, n + 4); //handles the second 4 six-bit bytes
|
||||||
|
|
||||||
|
uint8_t zn = (_zn + (63 - 2 * n)) % (63 - n);
|
||||||
|
uint8_t zn4 = (_zn4 + (64 - 2 * n)) % (64 - n);
|
||||||
|
|
||||||
|
pushbackSixBitByte(&c, zn, n);
|
||||||
|
pushbackSixBitByte(&c, zn4, n + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//restore the two most significant bytes (x and y)
|
||||||
|
c |= ((uint64_t)x_array[img] << 56);
|
||||||
|
c |= ((uint64_t)y << 48);
|
||||||
|
if (g_debugMode > 0){
|
||||||
|
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
|
||||||
|
printState("origin_r1", c);
|
||||||
|
}
|
||||||
|
//reverse the swapZbalues function to get the original six-bit byte order
|
||||||
|
uint64_t original_z = swapZvalues(c);
|
||||||
|
|
||||||
|
if (g_debugMode > 0){
|
||||||
|
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
|
||||||
|
printState("origin_r2", original_z);
|
||||||
|
PrintAndLogEx(INFO, "--------------------------");
|
||||||
|
}
|
||||||
|
//run pre-image through hash0
|
||||||
|
uint8_t img_div_key[8] = {0};
|
||||||
|
hash0(original_z, img_div_key); //commented to avoid log spam
|
||||||
|
|
||||||
|
//verify result, if it matches add it to the list as a valid pre-image
|
||||||
|
bool image_match = true;
|
||||||
|
for(int v=0; v<8; v++){
|
||||||
|
if(img_div_key[v] != k[v]){ //compare against input key k
|
||||||
|
image_match = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t des_pre_image[8] = {0};
|
||||||
|
x_num_to_bytes(original_z,sizeof(original_z),des_pre_image);
|
||||||
|
|
||||||
|
if(image_match){
|
||||||
|
PrintAndLogEx(INFO, _GREEN_("Valid pre-image: ")_YELLOW_("%s"), sprint_hex(des_pre_image, sizeof(des_pre_image)));
|
||||||
|
}else if (!image_match && g_debugMode > 0){
|
||||||
|
PrintAndLogEx(INFO, _RED_("Invalid pre-image: %s"), sprint_hex(des_pre_image, sizeof(des_pre_image)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Performs Elite-class key diversification
|
* @brief Performs Elite-class key diversification
|
||||||
* @param csn
|
* @param csn
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void hash0(uint64_t c, uint8_t k[8]);
|
void hash0(uint64_t c, uint8_t k[8]);
|
||||||
|
void invert_hash0(uint8_t k[8]);
|
||||||
int doKeyTests(void);
|
int doKeyTests(void);
|
||||||
/**
|
/**
|
||||||
* @brief Performs Elite-class key diversification
|
* @brief Performs Elite-class key diversification
|
||||||
|
|
Loading…
Reference in a new issue