mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
ulaes: add verify_cmac, display counters in mfu info, fix sig when schann in mfu info
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
#include "BigBuf.h"
|
||||
#include "dbprint.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "iso14443a.h"
|
||||
|
||||
static ulaes_key_t g_secure_session = {
|
||||
.counter = 0,
|
||||
@@ -173,3 +175,27 @@ void append_cmac(uint8_t *d, size_t n) {
|
||||
|
||||
increase_session_counter();
|
||||
}
|
||||
|
||||
int verify_cmac(uint8_t *d, size_t n, bool verify_crc) {
|
||||
// n = data size without cmac and without crc
|
||||
uint8_t chk_d[n + ULAES_CMAC8_SIZE + 2];
|
||||
memcpy(chk_d, d, n);
|
||||
memset(chk_d + n, 0, sizeof(chk_d) - n);
|
||||
append_cmac(chk_d, n);
|
||||
if (memcmp(chk_d + n, d + n, ULAES_CMAC8_SIZE) != 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("CMAC response error.");
|
||||
}
|
||||
return PM3_ECRC;
|
||||
}
|
||||
if (verify_crc) {
|
||||
AddCrc14A(chk_d, n + ULAES_CMAC8_SIZE);
|
||||
if (memcmp(chk_d + n + ULAES_CMAC8_SIZE, d + n + ULAES_CMAC8_SIZE, 2) != 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("CRC response error.");
|
||||
}
|
||||
return PM3_ECRC;
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define ULAES_CMAC8_SIZE 8
|
||||
|
||||
typedef struct {
|
||||
bool use_schann;
|
||||
uint8_t cmac_sk1[16];
|
||||
@@ -41,5 +43,6 @@ bool get_session_channel(void);
|
||||
void ulaes_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[16]);
|
||||
void ulaes_cmac8(uint8_t *cmac, uint8_t *mac);
|
||||
void append_cmac(uint8_t *d, size_t n);
|
||||
int verify_cmac(uint8_t *d, size_t n, bool verify_crc);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -868,7 +868,7 @@ void MifareUSetKey(mful_setkey_t *packet) {
|
||||
|
||||
if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
+44
-39
@@ -595,48 +595,54 @@ static int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
|
||||
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
|
||||
uint16_t len = 0;
|
||||
uint8_t offset = 0;
|
||||
|
||||
if (get_session_channel()) {
|
||||
offset = 8;
|
||||
uint8_t cmd[2 + 8] = { ISO14443A_CMD_READBLOCK, blockNo };
|
||||
uint8_t cmd[2 + ULAES_CMAC8_SIZE] = { ISO14443A_CMD_READBLOCK, blockNo };
|
||||
append_cmac(cmd, 2);
|
||||
len = mifare_sendcmd_schann(cmd, sizeof(cmd), receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL);
|
||||
if (len != 16 + ULAES_CMAC8_SIZE + 2) {
|
||||
if (len == 1) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
}
|
||||
return PM3_ECARDEXCHANGE;
|
||||
} else {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
}
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
int ret = verify_cmac(receivedAnswer, 16, true);
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL);
|
||||
}
|
||||
|
||||
if (len == 1) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
if (len != 16 + 2) {
|
||||
if (len == 1) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
}
|
||||
return PM3_ECARDEXCHANGE;
|
||||
} else {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
}
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
return PM3_ECARDEXCHANGE;
|
||||
}
|
||||
|
||||
// Ev1 / Ul-C == 18 bytes response
|
||||
// UL-Aes in secure messaging == 26
|
||||
if (len != 18 + offset) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AddCrc14A(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd CRC response error.");
|
||||
return PM3_ECRC;
|
||||
}
|
||||
}
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
memcpy(bt, receivedAnswer + 16 + offset, 2);
|
||||
AddCrc14A(receivedAnswer, 16 + offset);
|
||||
if (bt[0] != receivedAnswer[16 + offset] || bt[1] != receivedAnswer[17 + offset]) {
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Cmd CRC response error.");
|
||||
}
|
||||
return PM3_ECRC;
|
||||
}
|
||||
|
||||
// we are skipping verifying the cmac since we don't care.
|
||||
|
||||
// increase counter for the read response
|
||||
increase_session_counter();
|
||||
|
||||
memcpy(blockData, receivedAnswer, 16);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
@@ -822,21 +828,20 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
||||
uint16_t len = 0;
|
||||
|
||||
if (get_session_channel()) {
|
||||
uint8_t cmd[2 + 4 + 8] = { MIFARE_ULC_WRITE, blockNo };
|
||||
uint8_t cmd[2 + 4 + ULAES_CMAC8_SIZE] = { MIFARE_ULC_WRITE, blockNo };
|
||||
memcpy(cmd + 2, blockData, 4);
|
||||
append_cmac(cmd, 2 + 4);
|
||||
len = mifare_sendcmd_schann(cmd, sizeof(cmd), receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL);
|
||||
// we are skipping verifying the cmac, since we don't care.
|
||||
// increase counter for the write response
|
||||
increase_session_counter();
|
||||
|
||||
if (len != 10) {
|
||||
if (len != ULAES_CMAC8_SIZE + 2) {
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
Dbprintf("Cmd Send Error: " _RED_("%d"), len);
|
||||
}
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
int ret = verify_cmac(receivedAnswer, 0, true);
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
|
||||
+20
-15
@@ -1459,27 +1459,31 @@ static int ulev1_print_configuration(uint64_t tagtype, uint8_t *data, uint8_t st
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ulev1_print_counters(void) {
|
||||
static int ulev1_print_counters(uint64_t tagtype, bool use_schann) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counters"));
|
||||
uint8_t tear[1] = {0};
|
||||
uint8_t counter[3] = {0, 0, 0};
|
||||
int len = 0;
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
ulev1_readTearing(i, tear, sizeof(tear));
|
||||
len = ulev1_readCounter(i, counter, sizeof(counter), false);
|
||||
len = ulev1_readCounter(i, counter, sizeof(counter), use_schann);
|
||||
if (len == 3) {
|
||||
PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
|
||||
, tear[0]
|
||||
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
if ((tagtype & MFU_TT_UL_AES) != MFU_TT_UL_AES) {
|
||||
ulev1_readTearing(i, tear, sizeof(tear));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
|
||||
, tear[0]
|
||||
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
|
||||
int index = -1;
|
||||
if (signature_len == 32) {
|
||||
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFUL);
|
||||
@@ -2618,13 +2622,13 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
// do counters and signature first (don't neet auth)
|
||||
// do counters and signature first (don't need auth)
|
||||
|
||||
// ul counters are different than ntag counters
|
||||
if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_AES))) {
|
||||
if (ulev1_print_counters() != 3) {
|
||||
if (ulev1_print_counters(tagtype, use_schann) != 3) {
|
||||
// failed - re-select
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, pack, sizeof(pack), false) == PM3_ESOFT) {
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, pack, sizeof(pack), use_schann) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
@@ -3631,7 +3635,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
|
||||
if (has_auth_key) {
|
||||
uint8_t dummy_pack[] = {0, 0};
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false);
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann);
|
||||
} else {
|
||||
ul_select(&card);
|
||||
}
|
||||
@@ -3651,11 +3655,11 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
|
||||
if (has_auth_key) {
|
||||
uint8_t dummy_pack[] = {0, 0};
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false);
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann);
|
||||
} else {
|
||||
ul_select(&card);
|
||||
}
|
||||
ulev1_readCounter(n, &get_counter_tearing[n][0], 3, false);
|
||||
ulev1_readCounter(n, &get_counter_tearing[n][0], 3, use_schann);
|
||||
|
||||
if (has_auth_key) {
|
||||
uint8_t dummy_pack[] = {0, 0};
|
||||
@@ -3670,12 +3674,12 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
|
||||
if (has_auth_key) {
|
||||
uint8_t dummy_pack[] = {0, 0};
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false);
|
||||
ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann);
|
||||
} else {
|
||||
ul_select(&card);
|
||||
}
|
||||
|
||||
ulev1_readSignature(get_signature, sizeof(get_signature), false);
|
||||
ulev1_readSignature(get_signature, sizeof(get_signature), use_schann);
|
||||
DropField();
|
||||
}
|
||||
|
||||
@@ -5023,6 +5027,7 @@ static int CmdHF14AMfUSetKey(const char *Cmd) {
|
||||
|
||||
SendCommandNG(CMD_HF_MIFAREU_SETKEY, (uint8_t *)&packet, sizeof(packet));
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFAREU_SETKEY, &resp, 1500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
|
||||
@@ -195,8 +195,6 @@ int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signat
|
||||
|
||||
int originality_check_print(uint8_t *signature, int signature_len, int index) {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) {
|
||||
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
||||
|
||||
Reference in New Issue
Block a user