use DEFINES instead

This commit is contained in:
iceman1001 2024-09-13 13:43:32 +02:00
commit 77e94c8047
3 changed files with 50 additions and 33 deletions

View file

@ -166,9 +166,6 @@ static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
}; };
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
for (uint8_t i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) { for (uint8_t i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
int dl = 0; int dl = 0;
@ -178,6 +175,11 @@ static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, 32, true); int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, 32, true);
if (res == 0) { if (res == 0) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys[i].desc); PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value); PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
@ -186,6 +188,7 @@ static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
} }
return PM3_ESOFT; return PM3_ESOFT;
} }

View file

@ -183,9 +183,9 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
register uint8_t j; register uint8_t j;
for (j = 0; j < size; j++) { for (j = 0; j < size; j++) {
if (par_list == 0) { if (par_list == 0) {
num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6)); num_to_bytes(last_keylist[i * max_keys + j], MIFARE_KEY_SIZE, keyBlock + (j * MIFARE_KEY_SIZE));
} else { } else {
num_to_bytes(keylist[i * max_keys + j], 6, keyBlock + (j * 6)); num_to_bytes(keylist[i * max_keys + j], MIFARE_KEY_SIZE, keyBlock + (j * MIFARE_KEY_SIZE));
} }
} }
@ -209,7 +209,9 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
} }
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) { int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
if (key) {
*key = -1; *key = -1;
}
clearCommandBuffer(); clearCommandBuffer();
uint8_t data[PM3_CMD_DATA_SIZE] = {0}; uint8_t data[PM3_CMD_DATA_SIZE] = {0};
data[0] = keyType; data[0] = keyType;
@ -217,8 +219,8 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc
data[2] = clear_trace; data[2] = clear_trace;
data[3] = 0; data[3] = 0;
data[4] = keycnt; data[4] = keycnt;
memcpy(data + 5, keyBlock, 6 * keycnt); memcpy(data + 5, keyBlock, MIFARE_KEY_SIZE * keycnt);
SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + 6 * keycnt)); SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + MIFARE_KEY_SIZE * keycnt));
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500) == false) { if (WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500) == false) {
@ -229,7 +231,7 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc
} }
struct kr { struct kr {
uint8_t key[6]; uint8_t key[MIFARE_KEY_SIZE];
bool found; bool found;
} PACKED; } PACKED;
struct kr *keyresult = (struct kr *)&resp.data.asBytes; struct kr *keyresult = (struct kr *)&resp.data.asBytes;
@ -261,7 +263,7 @@ int mfCheckKeys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChun
uint32_t timeout = 0; uint32_t timeout = 0;
while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
if (! quiet) { if (quiet == false) {
PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF); PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF);
fflush(stdout); fflush(stdout);
} }
@ -278,7 +280,7 @@ int mfCheckKeys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChun
} }
t2 = msclock() - t2; t2 = msclock() - t2;
if (timeout && ! quiet) { if (timeout && (quiet == false)) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} }
@ -327,12 +329,12 @@ int mfCheckKeys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChun
for (int i = 0; i < sectorsCnt; i++) { for (int i = 0; i < sectorsCnt; i++) {
// key A // key A
if (!e_sector[i].foundKey[0]) { if (!e_sector[i].foundKey[0]) {
e_sector[i].Key[0] = bytes_to_num(tmp[i].keyA, 6); e_sector[i].Key[0] = bytes_to_num(tmp[i].keyA, MIFARE_KEY_SIZE);
e_sector[i].foundKey[0] = arr[(i * 2) ]; e_sector[i].foundKey[0] = arr[(i * 2) ];
} }
// key B // key B
if (!e_sector[i].foundKey[1]) { if (!e_sector[i].foundKey[1]) {
e_sector[i].Key[1] = bytes_to_num(tmp[i].keyB, 6); e_sector[i].Key[1] = bytes_to_num(tmp[i].keyB, MIFARE_KEY_SIZE);
e_sector[i].foundKey[1] = arr[(i * 2) + 1 ]; e_sector[i].foundKey[1] = arr[(i * 2) + 1 ];
} }
} }
@ -398,7 +400,7 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) {
if (resp.status != PM3_SUCCESS) return resp.status; if (resp.status != PM3_SUCCESS) return resp.status;
struct kr { struct kr {
uint8_t key[6]; uint8_t key[MIFARE_KEY_SIZE];
bool found; bool found;
} PACKED; } PACKED;
struct kr *keyresult = (struct kr *)&resp.data.asBytes; struct kr *keyresult = (struct kr *)&resp.data.asBytes;
@ -422,7 +424,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint64_t *r
// Generate all possible keys for the first two unknown bytes. // Generate all possible keys for the first two unknown bytes.
for (uint16_t i = 0; i < 0xFFFF; ++i) { for (uint16_t i = 0; i < 0xFFFF; ++i) {
uint32_t j = i * 6; uint32_t j = i * MIFARE_KEY_SIZE;
candidates[0 + j] = i >> 8; candidates[0 + j] = i >> 8;
candidates[1 + j] = i; candidates[1 + j] = i;
candidates[2 + j] = key[2]; candidates[2 + j] = key[2];
@ -604,7 +606,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt); PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt);
memset(resultKey, 0, 6); memset(resultKey, 0, MIFARE_KEY_SIZE);
uint64_t key64 = -1; uint64_t key64 = -1;
// The list may still contain several key candidates. Test each of them with mfCheckKeys // The list may still contain several key candidates. Test each of them with mfCheckKeys
@ -620,7 +622,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
register uint8_t j; register uint8_t j;
for (j = 0; j < size; j++) { for (j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6); num_to_bytes(key64, 6, keyBlock + j * MIFARE_KEY_SIZE);
} }
if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) {
@ -632,13 +634,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]", PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]",
package->block, package->block,
package->keytype ? 'B' : 'A', package->keytype ? 'B' : 'A',
sprint_hex_inrow(resultKey, 6) sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE)
); );
} else { } else {
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x -- found valid key [ " _GREEN_("%s") " ]", PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x -- found valid key [ " _GREEN_("%s") " ]",
package->block, package->block,
MIFARE_AUTH_KEYA + package->keytype, MIFARE_AUTH_KEYA + package->keytype,
sprint_hex_inrow(resultKey, 6) sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE)
); );
} }
@ -821,11 +823,13 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
*/ */
uint32_t keycnt = statelists[0].len; uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out; if (keycnt == 0) {
goto out;
}
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt); PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt);
memset(resultKey, 0, 6); memset(resultKey, 0, MIFARE_KEY_SIZE);
// The list may still contain several key candidates. Test each of them with mfCheckKeys // The list may still contain several key candidates. Test each of them with mfCheckKeys
uint32_t maxkeysinblock = IfPm3Flash() ? 1000 : KEYS_IN_BLOCK; uint32_t maxkeysinblock = IfPm3Flash() ? 1000 : KEYS_IN_BLOCK;
@ -838,7 +842,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
if (IfPm3Flash() && keycnt > 70) { if (IfPm3Flash() && keycnt > 70) {
// used for mfCheckKeys_file, which needs a header // used for mfCheckKeys_file, which needs a header
mem = calloc((maxkeysinblock * 6) + 5, sizeof(uint8_t)); mem = calloc((maxkeysinblock * MIFARE_KEY_SIZE) + 5, sizeof(uint8_t));
if (mem == NULL) { if (mem == NULL) {
free(statelists[0].head.slhead); free(statelists[0].head.slhead);
return PM3_EMALLOC; return PM3_EMALLOC;
@ -854,7 +858,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
} else { } else {
// used for mfCheckKeys, which adds its own header. // used for mfCheckKeys, which adds its own header.
mem = calloc((maxkeysinblock * 6), sizeof(uint8_t)); mem = calloc((maxkeysinblock * MIFARE_KEY_SIZE), sizeof(uint8_t));
if (mem == NULL) { if (mem == NULL) {
free(statelists[0].head.slhead); free(statelists[0].head.slhead);
return PM3_EMALLOC; return PM3_EMALLOC;
@ -882,7 +886,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
// copy x keys to device. // copy x keys to device.
for (uint32_t j = 0; j < chunk; j++) { for (uint32_t j = 0; j < chunk; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64);
num_to_bytes(key64, 6, p_keyblock + j * 6); num_to_bytes(key64, MIFARE_KEY_SIZE, p_keyblock + j * MIFARE_KEY_SIZE);
} }
// check a block of generated key candidates. // check a block of generated key candidates.
@ -892,7 +896,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
mem[4] = (chunk & 0xFF); mem[4] = (chunk & 0xFF);
// upload to flash. // upload to flash.
res = flashmem_spiffs_load((char *)fn, mem, 5 + (chunk * 6)); res = flashmem_spiffs_load((char *)fn, mem, 5 + (chunk * MIFARE_KEY_SIZE));
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "\nSPIFFS upload failed"); PrintAndLogEx(WARNING, "\nSPIFFS upload failed");
free(mem); free(mem);
@ -908,7 +912,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
free(statelists[0].head.slhead); free(statelists[0].head.slhead);
free(mem); free(mem);
num_to_bytes(key64, 6, resultKey); num_to_bytes(key64, MIFARE_KEY_SIZE, resultKey);
if (IfPm3Flash() && keycnt > 70) if (IfPm3Flash() && keycnt > 70)
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -916,7 +920,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
PrintAndLogEx(SUCCESS, "target block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]", PrintAndLogEx(SUCCESS, "target block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]",
package->block, package->block,
package->keytype ? 'B' : 'A', package->keytype ? 'B' : 'A',
sprint_hex_inrow(resultKey, 6) sprint_hex_inrow(resultKey, MIFARE_KEY_SIZE)
); );
return PM3_SUCCESS; return PM3_SUCCESS;
} else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) { } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
@ -1099,7 +1103,7 @@ int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *
} }
} }
PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, 16)); PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, sizeof(block0)));
if (wipecard) { if (wipecard) {
params |= MAGIC_WIPE; params |= MAGIC_WIPE;
@ -1454,31 +1458,39 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
return NONCE_FAIL; return NONCE_FAIL;
} }
if (verbose && (resp.data.asBytes[0] == NONCE_STATIC_ENC)) { if (verbose && (resp.data.asBytes[0] == NONCE_STATIC_ENC)) {
uint32_t uid = resp.data.asBytes[1] << 24 | uint32_t uid = resp.data.asBytes[1] << 24 |
resp.data.asBytes[2] << 16 | resp.data.asBytes[2] << 16 |
resp.data.asBytes[3] << 8 | resp.data.asBytes[3] << 8 |
resp.data.asBytes[4]; resp.data.asBytes[4];
uint32_t nt = resp.data.asBytes[5] << 24 | uint32_t nt = resp.data.asBytes[5] << 24 |
resp.data.asBytes[6] << 16 | resp.data.asBytes[6] << 16 |
resp.data.asBytes[7] << 8 | resp.data.asBytes[7] << 8 |
resp.data.asBytes[8]; resp.data.asBytes[8];
uint32_t ntenc = resp.data.asBytes[9] << 24 | uint32_t ntenc = resp.data.asBytes[9] << 24 |
resp.data.asBytes[10] << 16 | resp.data.asBytes[10] << 16 |
resp.data.asBytes[11] << 8 | resp.data.asBytes[11] << 8 |
resp.data.asBytes[12]; resp.data.asBytes[12];
uint8_t ntencparenc = resp.data.asBytes[13]; uint8_t ntencparenc = resp.data.asBytes[13];
// recompute nt on client, just because // recompute nt on client, just because
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
uint64_t ui64key = bytes_to_num(key_nested, 6); uint64_t ui64key = bytes_to_num(key_nested, 6);
crypto1_init(pcs, ui64key); // key_nested crypto1_init(pcs, ui64key); // key_nested
uint32_t ks = crypto1_word(pcs, ntenc ^ uid, 1); uint32_t ks = crypto1_word(pcs, ntenc ^ uid, 1);
uint32_t mynt = ks ^ ntenc; uint32_t mynt = ks ^ ntenc;
if (mynt != nt) { if (mynt != nt) {
PrintAndLogEx(ERR, "Client computed nT " _YELLOW_("%08x") " does not match ARM computed nT " _YELLOW_("%08x"), mynt, nt); PrintAndLogEx(ERR, "Client computed nT " _YELLOW_("%08x") " does not match ARM computed nT " _YELLOW_("%08x"), mynt, nt);
} }
ntencparenc >>= 4; ntencparenc >>= 4;
// [...] Additionally, the bit of keystream used to encrypt the parity bits is reused to encrypt the next bit of plaintext. // [...] Additionally, the bit of keystream used to encrypt the parity bits is reused to encrypt the next bit of plaintext.
// we can decrypt first 3 parity bits, not last one as it's using future keystream // we can decrypt first 3 parity bits, not last one as it's using future keystream
@ -1491,7 +1503,8 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
(ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1, (ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1,
ks, nt, ks, nt,
oddparity8((nt >> 24) & 0xFF), oddparity8((nt >> 16) & 0xFF), oddparity8((nt >> 8) & 0xFF), oddparity8(nt & 0xFF), oddparity8((nt >> 24) & 0xFF), oddparity8((nt >> 16) & 0xFF), oddparity8((nt >> 8) & 0xFF), oddparity8(nt & 0xFF),
nonce_distance(0, nt)); nonce_distance(0, nt)
);
} else { } else {
PrintAndLogEx(INFO, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _YELLOW_("%08x") " | nT " _YELLOW_("%08x") " par " _YELLOW_("%i%i%i%i") " | " _RED_("not lfsr16") " (wrong key)", PrintAndLogEx(INFO, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _YELLOW_("%08x") " | nT " _YELLOW_("%08x") " par " _YELLOW_("%i%i%i%i") " | " _RED_("not lfsr16") " (wrong key)",
ntenc, ntenc,

View file

@ -23,6 +23,7 @@
#include "common.h" #include "common.h"
#include "util.h" // FILE_PATH_SIZE #include "util.h" // FILE_PATH_SIZE
#include "mifaredefault.h" // consts
#include "protocol_vigik.h" #include "protocol_vigik.h"
#define MIFARE_SECTOR_RETRY 10 #define MIFARE_SECTOR_RETRY 10
@ -60,14 +61,14 @@ typedef struct {
} sector_t; } sector_t;
typedef struct { typedef struct {
uint8_t keyA[6]; uint8_t keyA[MIFARE_KEY_SIZE];
uint8_t keyB[6]; uint8_t keyB[MIFARE_KEY_SIZE];
//uint8_t foundKey[2]; //uint8_t foundKey[2];
} icesector_t; } icesector_t;
#define KEYS_IN_BLOCK ((PM3_CMD_DATA_SIZE - 5) / 6) #define KEYS_IN_BLOCK ((PM3_CMD_DATA_SIZE - 5) / MIFARE_KEY_SIZE)
#define KEYBLOCK_SIZE (KEYS_IN_BLOCK * 6) #define KEYBLOCK_SIZE (KEYS_IN_BLOCK * MIFARE_KEY_SIZE)
#define CANDIDATE_SIZE (0xFFFF * 6) #define CANDIDATE_SIZE (0xFFFF * MIFARE_KEY_SIZE)
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key);
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate); int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate);