mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
hf mfu setkey: supports ulc/ulaes auth and ulaes schann
This commit is contained in:
+1
-1
@@ -1877,7 +1877,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFAREU_SETKEY: {
|
||||
MifareUSetKey(packet->oldarg[0], packet->data.asBytes);
|
||||
MifareUSetKey((mful_setkey_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_READSC: {
|
||||
|
||||
+1
-1
@@ -3441,7 +3441,7 @@ int iso14443a_fast_select_card(const uint8_t *uid_ptr, uint8_t num_cascades) {
|
||||
}
|
||||
|
||||
void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||
|
||||
set_session_channel(false);
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
|
||||
+30
-21
@@ -856,15 +856,7 @@ void MifareUWriteBlockCompat(mful_writeblock_t *packet) {
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
void MifareUSetKey(uint8_t arg0, uint8_t *datain) {
|
||||
|
||||
uint8_t key[16] = {0x00};
|
||||
if (arg0 < 1 || arg0 > 3) {
|
||||
OnError(0);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(key, datain, 16);
|
||||
void MifareUSetKey(mful_setkey_t *packet) {
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
@@ -880,34 +872,51 @@ void MifareUSetKey(uint8_t arg0, uint8_t *datain) {
|
||||
return;
|
||||
};
|
||||
|
||||
bool useCKey = (packet->keytype == 1); // UL_C
|
||||
bool useAESKey = (packet->keytype == 3); // UL_AES
|
||||
|
||||
uint8_t start_block = 4; // just to be safe
|
||||
switch (arg0) {
|
||||
case 1: // UL-C
|
||||
start_block = 44;
|
||||
break;
|
||||
case 2: // UL-AES DataProtKey
|
||||
if (useCKey) { // UL-C
|
||||
start_block = 44;
|
||||
} else if (useAESKey) { // UL-AES
|
||||
if (packet->key_index == 0) { // UL-AES DataProtKey
|
||||
start_block = 48;
|
||||
break;
|
||||
case 3: // UL-AES UIDRetrKey
|
||||
} else if (packet->key_index == 1) { // UL-AES UIDRetrKey
|
||||
start_block = 52;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// UL-C authentication
|
||||
if (useCKey && packet->has_auth_key) {
|
||||
if (mifare_ultra_3des_auth(packet->auth_key, true) == 0) {
|
||||
OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// UL-AES authentication
|
||||
if (useAESKey && packet->has_auth_key) {
|
||||
if (mifare_ultra_aes_auth(0, packet->auth_key, packet->use_schann, true) == 0) {
|
||||
OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (mifare_ultra_writeblock(start_block + i, key + (i * 4)) != PM3_SUCCESS) {
|
||||
if (mifare_ultra_writeblock(start_block + i, packet->key + (i * 4)) != PM3_SUCCESS) {
|
||||
if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error");
|
||||
OnError(start_block + i);
|
||||
OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
if (mifare_ultra_halt()) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error");
|
||||
OnError(0);
|
||||
OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT);
|
||||
return;
|
||||
};
|
||||
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
reply_ng(CMD_HF_MIFAREU_SETKEY, PM3_SUCCESS, NULL, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work
|
||||
void MifareSetMod(uint8_t *datain);
|
||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
||||
|
||||
void MifareUSetKey(uint8_t arg0, uint8_t *datain);
|
||||
void MifareUSetKey(mful_setkey_t *packet);
|
||||
void OnSuccessMagic(void);
|
||||
void OnErrorMagic(uint8_t reason);
|
||||
|
||||
|
||||
+97
-40
@@ -4927,6 +4927,8 @@ static int CmdHF14AMfUSetKey(const char *Cmd) {
|
||||
arg_str0("k", "key", "<hex>", "New key (16 hex bytes)"),
|
||||
arg_int0("i", "idx", "<0..1>", "New key index (def: 0), only for UL-AES"),
|
||||
arg_lit0("l", NULL, "Swap entered keys' endianness"),
|
||||
arg_str0(NULL, "usekey", "<hex>", "Current UL-C 3DES or UL-AES DataProt key (16 hex bytes)"),
|
||||
arg_lit0(NULL, "schann", "use secure channel. Must have usekey"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
@@ -4937,6 +4939,11 @@ static int CmdHF14AMfUSetKey(const char *Cmd) {
|
||||
CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
|
||||
int key_index = arg_get_int_def(ctx, 2, 0);
|
||||
bool swap_endian = arg_get_lit(ctx, 3);
|
||||
int use_ak_len = 0;
|
||||
uint8_t use_authenticationkey[16] = {0x00};
|
||||
uint8_t *use_auth_key_ptr = use_authenticationkey;
|
||||
CLIGetHexWithReturn(ctx, 4, use_authenticationkey, &use_ak_len);
|
||||
bool use_schann = arg_get_lit(ctx, 5);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (ak_len != 16) {
|
||||
@@ -4948,6 +4955,19 @@ static int CmdHF14AMfUSetKey(const char *Cmd) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool has_auth_key = false;
|
||||
if (use_ak_len == 16) {
|
||||
has_auth_key = true;
|
||||
} else if (use_ak_len != 0) {
|
||||
PrintAndLogEx(WARNING, "usekey must be 16 hex bytes\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (use_schann && has_auth_key == false) {
|
||||
PrintAndLogEx(WARNING, "Secure channel must be called with usekey");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint64_t tagtype = GetHF14AMfU_Type();
|
||||
if (tagtype == MFU_TT_UL_ERROR) {
|
||||
return PM3_ESOFT;
|
||||
@@ -4968,25 +4988,49 @@ static int CmdHF14AMfUSetKey(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
|
||||
SendCommandMIX(CMD_HF_MIFAREU_SETKEY, 1, 0, 0, auth_key_ptr, sizeof(authenticationkey));
|
||||
} else if ((tagtype & MFU_TT_UL_AES) == MFU_TT_UL_AES) {
|
||||
SendCommandMIX(CMD_HF_MIFAREU_SETKEY, key_index + 2, 0, 0, auth_key_ptr, sizeof(authenticationkey));
|
||||
// Swap endianness of usekey
|
||||
if (swap_endian) {
|
||||
if (use_ak_len == 16) {
|
||||
if (((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C)) {
|
||||
use_auth_key_ptr = SwapEndian64(use_authenticationkey, use_ak_len, 8);
|
||||
} else if (((tagtype & MFU_TT_UL_AES) == MFU_TT_UL_AES)) {
|
||||
use_auth_key_ptr = SwapEndian64(use_authenticationkey, use_ak_len, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if ((resp.oldarg[0] & 0xff) == 1) {
|
||||
PrintAndLogEx(INFO, "New key... " _GREEN_("%s"), sprint_hex_inrow(authenticationkey, sizeof(authenticationkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
|
||||
return PM3_ESOFT;
|
||||
if (has_auth_key) {
|
||||
if (((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C)) {
|
||||
PrintAndLogEx(INFO, "Using 3des... " _GREEN_("%s"), sprint_hex_inrow(use_authenticationkey, use_ak_len));
|
||||
} else if (((tagtype & MFU_TT_UL_AES) == MFU_TT_UL_AES)) {
|
||||
PrintAndLogEx(INFO, "Using aes... " _GREEN_("%s"), sprint_hex_inrow(use_authenticationkey, use_ak_len));
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
}
|
||||
|
||||
mful_setkey_t packet = {
|
||||
.has_auth_key = has_auth_key,
|
||||
.use_schann = use_schann,
|
||||
.key_index = key_index,
|
||||
.keytype = ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) ? 1 : 3, // 1=ULC 3=ULAES
|
||||
};
|
||||
if (has_auth_key) {
|
||||
memcpy(packet.auth_key, use_auth_key_ptr, 16);
|
||||
}
|
||||
memcpy(packet.key, auth_key_ptr, 16);
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
|
||||
SendCommandNG(CMD_HF_MIFAREU_SETKEY, (uint8_t *)&packet, sizeof(packet));
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFAREU_SETKEY, &resp, 1500) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "New key... " _GREEN_("%s"), sprint_hex_inrow(authenticationkey, sizeof(authenticationkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -6770,6 +6814,13 @@ static int CmdHF14AMfuWipe(const char *Cmd) {
|
||||
|
||||
PrintAndLogEx(INFO, "-----+-----------------------------");
|
||||
|
||||
mful_setkey_t packet = {
|
||||
.has_auth_key = false,
|
||||
.use_schann = false,
|
||||
.key_index = 0,
|
||||
};
|
||||
PacketResponseNG resp;
|
||||
|
||||
ulc:
|
||||
|
||||
// UL-C - set 3-DES key
|
||||
@@ -6780,21 +6831,21 @@ ulc:
|
||||
0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46
|
||||
};
|
||||
uint8_t *def_key_ptr = SwapEndian64(defaultkey, 16, 8);
|
||||
packet.keytype = 1; // UL-C
|
||||
memcpy(packet.key, def_key_ptr, 16);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_SETKEY, 1, 0, 0, def_key_ptr, sizeof(defaultkey));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if ((resp.oldarg[0] & 0xff) == 1) {
|
||||
PrintAndLogEx(INFO, "Ultralight C new key... " _GREEN_("%s"), sprint_hex_inrow(defaultkey, sizeof(defaultkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
PrintAndLogEx(INFO, "Ultralight C new key... " _GREEN_("%s"), sprint_hex_inrow(defaultkey, sizeof(defaultkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
ulaes:
|
||||
@@ -6803,30 +6854,36 @@ ulaes:
|
||||
// Set AES keys
|
||||
uint8_t defaultkey[16] = { 0 };
|
||||
uint8_t *def_key_ptr = SwapEndian64(defaultkey, 16, 16);
|
||||
packet.keytype = 3; // UL-AES
|
||||
packet.key_index = 0;
|
||||
memcpy(packet.key, def_key_ptr, 16);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_SETKEY, 2, 0, 0, def_key_ptr, sizeof(defaultkey));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if ((resp.oldarg[0] & 0xff) != 1) {
|
||||
PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_SETKEY, 3, 0, 0, def_key_ptr, sizeof(defaultkey));
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if ((resp.oldarg[0] & 0xff) == 1) {
|
||||
PrintAndLogEx(INFO, "Ultralight AES new key... " _GREEN_("%s"), sprint_hex_inrow(defaultkey, sizeof(defaultkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Ultralight AES new DataProtKey... " _GREEN_("%s"), sprint_hex_inrow(defaultkey, sizeof(defaultkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
packet.key_index = 1;
|
||||
clearCommandBuffer();
|
||||
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) {
|
||||
PrintAndLogEx(INFO, "Ultralight AES new UIDRetrKey... " _GREEN_("%s"), sprint_hex_inrow(defaultkey, sizeof(defaultkey)));
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Failed writing key");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -414,6 +414,15 @@ typedef struct {
|
||||
uint8_t data[16];
|
||||
} PACKED mful_writeblock_t;
|
||||
|
||||
typedef struct {
|
||||
bool has_auth_key;
|
||||
bool use_schann;
|
||||
uint8_t auth_key[16];
|
||||
uint8_t keytype;
|
||||
uint8_t key_index;
|
||||
uint8_t key[16];
|
||||
} PACKED mful_setkey_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
uint8_t CSN[8];
|
||||
|
||||
Reference in New Issue
Block a user