cppcheck duplicatecondition

This commit is contained in:
Philippe Teuwen 2025-03-24 21:59:52 +01:00
commit 4fff85d6ed

View file

@ -1186,38 +1186,36 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
// 1. Verify passed parameters authenticate with the tag (safety check) // 1. Verify passed parameters authenticate with the tag (safety check)
// lf em 4x70 auth --rnd <rnd_1> --frn <frn_1> // lf em 4x70 auth --rnd <rnd_1> --frn <frn_1>
if (PM3_SUCCESS == result) { PrintAndLogEx(INFO, "Step 1. Verifying passed parameters authenticate with the tag (safety check)");
PrintAndLogEx(INFO, "Step 1. Verifying passed parameters authenticate with the tag (safety check)"); PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 auth --rnd %s --frn %s"), rnd_string, frn_string);
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 auth --rnd %s --frn %s"), rnd_string, frn_string);
em4x70_cmd_input_auth_t opts_auth = { em4x70_cmd_input_auth_t opts_auth = {
.use_parity = opts.parity, .use_parity = opts.parity,
.rn = opts.nonce, .rn = opts.nonce,
.frn = opts.frn, .frn = opts.frn,
}; };
em4x70_cmd_output_auth_t tag_grn; em4x70_cmd_output_auth_t tag_grn;
result = auth_em4x70(&opts_auth, &tag_grn); result = auth_em4x70(&opts_auth, &tag_grn);
if (PM3_ETIMEOUT == result) { if (PM3_ETIMEOUT == result) {
PrintAndLogEx(WARNING, "timeout while waiting for reply"); PrintAndLogEx(WARNING, "timeout while waiting for reply");
return result; return result;
} else if (PM3_SUCCESS != result) { } else if (PM3_SUCCESS != result) {
PrintAndLogEx(FAILED, "Authenticating with provided values ( " _RED_("fail") " )"); PrintAndLogEx(FAILED, "Authenticating with provided values ( " _RED_("fail") " )");
return result; return result;
} else if (memcmp(&opts.grn, &tag_grn, sizeof(ID48LIB_GRN)) != 0) { } else if (memcmp(&opts.grn, &tag_grn, sizeof(ID48LIB_GRN)) != 0) {
PrintAndLogEx(FAILED, "Authenticating with new key returned %02x %02x %02x" PrintAndLogEx(FAILED, "Authenticating with new key returned %02x %02x %02x"
, tag_grn.grn.grn[0] , tag_grn.grn.grn[0]
, tag_grn.grn.grn[1] , tag_grn.grn.grn[1]
, tag_grn.grn.grn[2] , tag_grn.grn.grn[2]
); );
PrintAndLogEx(FAILED, "Expected %s [maybe 5 lsb of key wrong?] ( " _RED_("fail") " )", grn_string); PrintAndLogEx(FAILED, "Expected %s [maybe 5 lsb of key wrong?] ( " _RED_("fail") " )", grn_string);
result = PM3_EWRONGANSWER; result = PM3_EWRONGANSWER;
return result; return result;
}
last_successful_step = 1;
} }
last_successful_step = 1;
// 2/3/4. Brute force the key bits in block 7,8,9 // 2/3/4. Brute force the key bits in block 7,8,9
// lf em 4x70 write -b N -d 0000 // lf em 4x70 write -b N -d 0000
@ -1232,98 +1230,88 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
em4x70_cmd_output_brute_t brute = {0}; em4x70_cmd_output_brute_t brute = {0};
// lf em 4x70 write -b N -d 0000 // lf em 4x70 write -b N -d 0000
if (PM3_SUCCESS == result) { PrintAndLogEx(INFO, "Step %d. Brute force the key bits in block %d", step, block);
PrintAndLogEx(INFO, "Step %d. Brute force the key bits in block %d", step, block); PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d 0000"), block);
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d 0000"), block);
em4x70_cmd_input_writeblock_t opt_write_zeros = { em4x70_cmd_input_writeblock_t opt_write_zeros = {
.use_parity = opts.parity, .use_parity = opts.parity,
.block = block, .block = block,
.value = {0x00, 0x00}, .value = {0x00, 0x00},
}; };
result = writeblock_em4x70(&opt_write_zeros, &tag_info); result = writeblock_em4x70(&opt_write_zeros, &tag_info);
if (PM3_ETIMEOUT == result) { if (PM3_ETIMEOUT == result) {
PrintAndLogEx(FAILED, "timeout while waiting for reply"); PrintAndLogEx(FAILED, "timeout while waiting for reply");
PrintAndLogEx(HINT, "Hint: Block %d data may have been overwritten. Manually restart at step %d", block, step); PrintAndLogEx(HINT, "Hint: Block %d data may have been overwritten. Manually restart at step %d", block, step);
return result; return result;
} else if (PM3_SUCCESS != result) { } else if (PM3_SUCCESS != result) {
PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block); PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block);
PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step); PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step);
return result; return result;
}
} }
// lf em 4x70 brute -b N --rnd <rnd_1> --frn <frn_1> // lf em 4x70 brute -b N --rnd <rnd_1> --frn <frn_1>
if (PM3_SUCCESS == result) { PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 brute -b %d --rnd %s --frn %s"), block, rnd_string, frn_string);
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 brute -b %d --rnd %s --frn %s"), block, rnd_string, frn_string);
em4x70_cmd_input_brute_t opts_brute = { em4x70_cmd_input_brute_t opts_brute = {
.use_parity = opts.parity, .use_parity = opts.parity,
.block = block, .block = block,
.rn = opts.nonce, .rn = opts.nonce,
.frn = opts.frn, .frn = opts.frn,
.partial_key_start = {0}, .partial_key_start = {0},
}; };
result = brute_em4x70(&opts_brute, &brute); result = brute_em4x70(&opts_brute, &brute);
if (PM3_ETIMEOUT == result) { if (PM3_ETIMEOUT == result) {
PrintAndLogEx(FAILED, "timeout while waiting for reply"); PrintAndLogEx(FAILED, "timeout while waiting for reply");
PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step); PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step);
return result; return result;
} else if (PM3_SUCCESS != result) { } else if (PM3_SUCCESS != result) {
PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block); PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block);
PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step); PrintAndLogEx(HINT, "Hint: Block %d data was overwritten. Manually restart at step %d", block, step);
return result; return result;
} else { } else {
PrintAndLogEx(INFO, " Found: Partial key in block %d is " _GREEN_("%02X%02X") PrintAndLogEx(INFO, " Found: Partial key in block %d is " _GREEN_("%02X%02X")
, block , block
, brute.partial_key[0] , brute.partial_key[0]
, brute.partial_key[1] , brute.partial_key[1]
); );
// Save the partial key... // Save the partial key...
if (block == 9) { if (block == 9) {
opts.key.k[0] = brute.partial_key[0]; opts.key.k[0] = brute.partial_key[0];
opts.key.k[1] = brute.partial_key[1]; opts.key.k[1] = brute.partial_key[1];
} else if (block == 8) { } else if (block == 8) {
opts.key.k[2] = brute.partial_key[0]; opts.key.k[2] = brute.partial_key[0];
opts.key.k[3] = brute.partial_key[1]; opts.key.k[3] = brute.partial_key[1];
} else if (block == 7) { } else if (block == 7) {
opts.key.k[4] = brute.partial_key[0]; opts.key.k[4] = brute.partial_key[0];
opts.key.k[5] = brute.partial_key[1]; opts.key.k[5] = brute.partial_key[1];
}
} }
} }
// lf em 4x70 write -b N -d <key_block_N> // lf em 4x70 write -b N -d <key_block_N>
if (PM3_SUCCESS == result) { PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d %02X%02X"), block, brute.partial_key[0], brute.partial_key[1]);
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 write -b %d -d %02X%02X"), block, brute.partial_key[0], brute.partial_key[1]);
em4x70_cmd_input_writeblock_t opt_write_zeros = { em4x70_cmd_input_writeblock_t opt_write_zeros2 = {
.use_parity = opts.parity, .use_parity = opts.parity,
.block = block, .block = block,
.value = {brute.partial_key[0], brute.partial_key[1]}, .value = {brute.partial_key[0], brute.partial_key[1]},
}; };
result = writeblock_em4x70(&opt_write_zeros, &tag_info); result = writeblock_em4x70(&opt_write_zeros2, &tag_info);
if (PM3_ETIMEOUT == result) { if (PM3_ETIMEOUT == result) {
PrintAndLogEx(FAILED, "timeout while waiting for reply"); PrintAndLogEx(FAILED, "timeout while waiting for reply");
PrintAndLogEx(HINT, "Hint: Block %d data (" _GREEN_("%02X%02X") ") may need to be rewritten", block, brute.partial_key[0], brute.partial_key[1]); PrintAndLogEx(HINT, "Hint: Block %d data (" _GREEN_("%02X%02X") ") may need to be rewritten", block, brute.partial_key[0], brute.partial_key[1]);
return result; return result;
} else if (PM3_SUCCESS != result) { } else if (PM3_SUCCESS != result) {
PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block); PrintAndLogEx(FAILED, "Writing block %d ( " _RED_("fail") " )", block);
PrintAndLogEx(HINT, "Hint: Block %d data (" _GREEN_("%02X%02X") ") may need to be rewritten", block, brute.partial_key[0], brute.partial_key[1]); PrintAndLogEx(HINT, "Hint: Block %d data (" _GREEN_("%02X%02X") ") may need to be rewritten", block, brute.partial_key[0], brute.partial_key[1]);
return result; return result;
}
} }
if (PM3_SUCCESS == result) { last_successful_step = step;
last_successful_step = step;
} else {
break;
}
} }
// The good news is that, if the above succeeded, then from this point forward, the tag remains in a known-good state. // The good news is that, if the above succeeded, then from this point forward, the tag remains in a known-good state.
@ -1332,108 +1320,102 @@ static int CmdEM4x70AutoRecover(const char *Cmd) {
// 5. Recover potential values of the lower 48 bits of the key // 5. Recover potential values of the lower 48 bits of the key
// lf em 4x70 recover --key <key_block_9><key_block_8><key_block_7> --rnd <rnd_1> --frn <frn_1> // lf em 4x70 recover --key <key_block_9><key_block_8><key_block_7> --rnd <rnd_1> --frn <frn_1>
if (PM3_SUCCESS == result) { PrintAndLogEx(INFO, "Step 5. Recover potential values of the lower 48 bits of the key");
PrintAndLogEx(INFO, "Step 5. Recover potential values of the lower 48 bits of the key"); PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 recover --key %s --rnd %s --frn %s --grn %s"), key_string, rnd_string, frn_string, grn_string);
PrintAndLogEx(HINT, "Hint: " _YELLOW_("lf em 4x70 recover --key %s --rnd %s --frn %s --grn %s"), key_string, rnd_string, frn_string, grn_string);
result = recover_em4x70(&opts, &data); result = recover_em4x70(&opts, &data);
if (PM3_EOVFLOW == result) { if (PM3_EOVFLOW == result) {
PrintAndLogEx(ERR, "Found more than %d potential keys. This is unexpected and likely a code failure.", MAXIMUM_ID48_RECOVERED_KEY_COUNT); PrintAndLogEx(ERR, "Found more than %d potential keys. This is unexpected and likely a code failure.", MAXIMUM_ID48_RECOVERED_KEY_COUNT);
return result; return result;
} else if (PM3_SUCCESS != result) { } else if (PM3_SUCCESS != result) {
PrintAndLogEx(ERR, "No potential keys recovered. This is unexpected and likely a code failure."); PrintAndLogEx(ERR, "No potential keys recovered. This is unexpected and likely a code failure.");
return result; return result;
} else { } else {
PrintAndLogEx(INFO, " Found " _GREEN_("%d") " potential keys", data.potential_key_count); PrintAndLogEx(INFO, " Found " _GREEN_("%d") " potential keys", data.potential_key_count);
for (uint8_t idx = 0; idx < data.potential_key_count; ++idx) { for (uint8_t idx = 0; idx < data.potential_key_count; ++idx) {
ID48LIB_KEY q = data.potential_keys[idx]; ID48LIB_KEY q = data.potential_keys[idx];
PrintAndLogEx(DEBUG, " Potential Key %d: %s %02X%02X%02X%02X%02X%02X" PrintAndLogEx(DEBUG, " Potential Key %d: %s %02X%02X%02X%02X%02X%02X"
, idx , idx
, key_string , key_string
, q.k[ 6] , q.k[ 6]
, q.k[ 7] , q.k[ 7]
, q.k[ 8] , q.k[ 8]
, q.k[ 9] , q.k[ 9]
, q.k[10] , q.k[10]
, q.k[11] , q.k[11]
); );
}
last_successful_step = 5;
} }
last_successful_step = 5;
} }
// 6. Verify which potential key is actually on the tag (using a different rnd/frn combination) // 6. Verify which potential key is actually on the tag (using a different rnd/frn combination)
// lf em 4x70 auth --rnd <rnd_2> --frn <frn_N> // lf em 4x70 auth --rnd <rnd_2> --frn <frn_N>
if (PM3_SUCCESS == result) { PrintAndLogEx(INFO, "Step 6. Verify which potential key is actually on the tag");
PrintAndLogEx(INFO, "Step 6. Verify which potential key is actually on the tag");
em4x70_cmd_input_verify_auth_t opts_v = { em4x70_cmd_input_verify_auth_t opts_v = {
.use_parity = opts.parity, .use_parity = opts.parity,
//.rn = {{0}}, //.rn = {{0}},
//.frn = {{0}}, //.frn = {{0}},
//.grn = {{0}}, //.grn = {{0}},
}; };
// TODO: retry a few time, if >1 key validated with the new nonce // TODO: retry a few time, if >1 key validated with the new nonce
bool continue_loop = true; bool continue_loop = true;
bool found_one_key = false; bool found_one_key = false;
bool found_more_than_one_key = false; bool found_more_than_one_key = false;
uint8_t first_validated_key_idx = 0xFF; uint8_t first_validated_key_idx = 0xFF;
for (uint8_t attempt = 0; continue_loop && (attempt < 10); ++attempt) { for (uint8_t attempt = 0; continue_loop && (attempt < 10); ++attempt) {
continue_loop = false; continue_loop = false;
found_one_key = false; found_one_key = false;
found_more_than_one_key = false; found_more_than_one_key = false;
first_validated_key_idx = 0xFF; first_validated_key_idx = 0xFF;
fill_buffer_prng_bytes(&opts_v.rn, sizeof(ID48LIB_NONCE)); fill_buffer_prng_bytes(&opts_v.rn, sizeof(ID48LIB_NONCE));
for (uint8_t i = 0; i < data.potential_key_count; ++i) { for (uint8_t i = 0; i < data.potential_key_count; ++i) {
// generate the alternate frn/grn for this key + nonce combo // generate the alternate frn/grn for this key + nonce combo
id48lib_generator(&data.potential_keys[i], &opts_v.rn, &opts_v.frn, &opts_v.grn); id48lib_generator(&data.potential_keys[i], &opts_v.rn, &opts_v.frn, &opts_v.grn);
int tmpResult = verify_auth_em4x70(&opts_v); int tmpResult = verify_auth_em4x70(&opts_v);
if (PM3_SUCCESS == tmpResult) { if (PM3_SUCCESS == tmpResult) {
if (!found_one_key) { if (!found_one_key) {
first_validated_key_idx = i; first_validated_key_idx = i;
found_one_key = true; found_one_key = true;
} else { } else {
found_more_than_one_key = true; found_more_than_one_key = true;
}
} }
} }
if (found_one_key == false) {
PrintAndLogEx(WARNING, "No potential keys validated. Will try again with different nonce");
continue_loop = true;
msleep(2000); // delay 2 seconds ... in case tag was bumped, etc.
} else if (found_more_than_one_key) {
PrintAndLogEx(WARNING, "Multiple potential keys validated. Will try different nonce");
continue_loop = true;
msleep(2000); // delay 2 seconds ... in case tag was bumped, etc.
} else {
last_successful_step = 6;
}
} }
if ((found_one_key == false) || found_more_than_one_key) { if (found_one_key == false) {
PrintAndLogEx(FAILED, "Unable to recover any of the multiple potential keys"); PrintAndLogEx(WARNING, "No potential keys validated. Will try again with different nonce");
PrintAndLogEx(FAILED, "Check tag for good coupling / position!"); continue_loop = true;
return PM3_EFAILED; msleep(2000); // delay 2 seconds ... in case tag was bumped, etc.
} else if (found_more_than_one_key) {
PrintAndLogEx(WARNING, "Multiple potential keys validated. Will try different nonce");
continue_loop = true;
msleep(2000); // delay 2 seconds ... in case tag was bumped, etc.
} else { } else {
// print the validated key to the string buffer (for step 7) last_successful_step = 6;
ID48LIB_KEY q = data.potential_keys[first_validated_key_idx];
snprintf(key_string, 25, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
q.k[ 0], q.k[ 1], q.k[ 2], q.k[ 3], q.k[ 4], q.k[ 5],
q.k[ 6], q.k[ 7], q.k[ 8], q.k[ 9], q.k[10], q.k[11]
);
} }
} }
if ((found_one_key == false) || found_more_than_one_key) {
PrintAndLogEx(FAILED, "Unable to recover any of the multiple potential keys");
PrintAndLogEx(FAILED, "Check tag for good coupling / position!");
return PM3_EFAILED;
} else {
// print the validated key to the string buffer (for step 7)
ID48LIB_KEY q = data.potential_keys[first_validated_key_idx];
snprintf(key_string, 25, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
q.k[ 0], q.k[ 1], q.k[ 2], q.k[ 3], q.k[ 4], q.k[ 5],
q.k[ 6], q.k[ 7], q.k[ 8], q.k[ 9], q.k[10], q.k[11]
);
}
// 7. Print the validated key // 7. Print the validated key
if (PM3_SUCCESS == result) { PrintAndLogEx(SUCCESS, "Recovered key... " _GREEN_("%s"), key_string);
PrintAndLogEx(SUCCESS, "Recovered key... " _GREEN_("%s"), key_string); last_successful_step = 7;
last_successful_step = 7;
}
// For posterity, step 7 used to do the following: // For posterity, step 7 used to do the following:
// 7. Print the validated key --OR-- Print that the tag is still OK --OR-- Print instructions on what to retry to recover tag to a good state // 7. Print the validated key --OR-- Print that the tag is still OK --OR-- Print instructions on what to retry to recover tag to a good state