mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-21 07:46:12 +08:00
Added encrypted comms to ReadData and WriteData commands
This allows reading and writing to the "proprietary" file (number 3), or file 2 if it's set to "full" communications mode.
This commit is contained in:
parent
6d290f1bae
commit
912c126266
|
@ -45,45 +45,6 @@
|
|||
#define NTAG424_CMD_AUTHENTICATE_EV2_FIRST_PART_1 0x71
|
||||
#define NTAG424_CMD_AUTHENTICATE_EV2_FIRST_PART_2 0xAF
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int CmdHF_ntag424_view(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf ntag424 view",
|
||||
"Print a NTAG 424 DNA dump file (bin/eml/json)",
|
||||
"hf ntag424 view -f hf-ntag424-01020304-dump.bin"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
|
||||
arg_lit0("v", "verbose", "Verbose output"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE];
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// read dump file
|
||||
uint8_t *dump = NULL;
|
||||
size_t bytes_read = NTAG424_MAX_BYTES;
|
||||
int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, NTAG424_MAX_BYTES);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
|
||||
PrintAndLogEx(INFO, "File size %zu bytes", bytes_read);
|
||||
}
|
||||
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Original from https://github.com/rfidhacking/node-sdm/
|
||||
//
|
||||
|
@ -115,6 +76,13 @@ typedef enum {
|
|||
COMM_FULL
|
||||
} ntag424_communication_mode_t;
|
||||
|
||||
const CLIParserOption ntag424_communication_mode_options[] = {
|
||||
{COMM_PLAIN, "plain"},
|
||||
{COMM_MAC, "mac"},
|
||||
{COMM_FULL, "encrypt"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
// -------------- File settings structs -------------------------
|
||||
// Enabling this bit in the settings will also reset the read counter to 0
|
||||
#define FILE_SETTINGS_OPTIONS_SDM_AND_MIRRORING (1 << 6)
|
||||
|
@ -231,7 +199,7 @@ static int ntag424_calc_file_write_settings_size(const ntag424_file_settings_t *
|
|||
return ntag424_calc_file_settings_size(settings) - 4;
|
||||
}
|
||||
|
||||
static void ntag424_calc_iv(ntag424_session_keys_t *session_keys, uint8_t *out_ivc) {
|
||||
static void ntag424_calc_send_iv(ntag424_session_keys_t *session_keys, uint8_t *out_ivc) {
|
||||
uint8_t iv_clear[] = { 0xa5, 0x5a,
|
||||
session_keys->ti[0], session_keys->ti[1], session_keys->ti[2], session_keys->ti[3],
|
||||
(uint8_t)(session_keys->command_counter), (uint8_t)(session_keys->command_counter >> 8),
|
||||
|
@ -242,11 +210,21 @@ static void ntag424_calc_iv(ntag424_session_keys_t *session_keys, uint8_t *out_i
|
|||
aes_encode(zero_iv, session_keys->encryption, iv_clear, out_ivc, 16);
|
||||
}
|
||||
|
||||
static void ntag424_calc_mac(ntag424_session_keys_t *session_keys, uint8_t command, uint8_t command_header, uint8_t *data, uint8_t datalen, uint8_t *out_mac) {
|
||||
static void ntag424_calc_recieve_iv(ntag424_session_keys_t *session_keys, uint8_t *out_ivc) {
|
||||
uint8_t iv_clear[] = { 0x5a, 0xa5,
|
||||
session_keys->ti[0], session_keys->ti[1], session_keys->ti[2], session_keys->ti[3],
|
||||
(uint8_t)(session_keys->command_counter), (uint8_t)(session_keys->command_counter >> 8),
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
uint8_t zero_iv[16] = {0};
|
||||
aes_encode(zero_iv, session_keys->encryption, iv_clear, out_ivc, 16);
|
||||
}
|
||||
|
||||
static void ntag424_calc_mac(ntag424_session_keys_t *session_keys, uint8_t command, uint8_t *data, uint8_t datalen, uint8_t *out_mac) {
|
||||
uint8_t mac_input_header[] = { command,
|
||||
(uint8_t)session_keys->command_counter, (uint8_t)(session_keys->command_counter >> 8),
|
||||
session_keys->ti[0], session_keys->ti[1], session_keys->ti[2], session_keys->ti[3],
|
||||
command_header,
|
||||
session_keys->ti[0], session_keys->ti[1], session_keys->ti[2], session_keys->ti[3]
|
||||
};
|
||||
|
||||
int mac_input_len = sizeof(mac_input_header) + datalen;
|
||||
|
@ -264,7 +242,7 @@ static void ntag424_calc_mac(ntag424_session_keys_t *session_keys, uint8_t comma
|
|||
free(mac_input);
|
||||
}
|
||||
|
||||
static int ntag424_comm_mac_apdu(APDU_t *apdu, int apdu_max_data_size, ntag424_session_keys_t *session_keys) {
|
||||
static int ntag424_comm_mac_apdu(APDU_t *apdu, int command_header_length, int apdu_max_data_size, ntag424_session_keys_t *session_keys) {
|
||||
|
||||
int size = apdu->lc;
|
||||
|
||||
|
@ -272,41 +250,45 @@ static int ntag424_comm_mac_apdu(APDU_t *apdu, int apdu_max_data_size, ntag424_s
|
|||
return PM3_EOVFLOW;
|
||||
}
|
||||
|
||||
ntag424_calc_mac(session_keys, apdu->ins, apdu->data[0], &apdu->data[1], size - 1, &apdu->data[size]);
|
||||
|
||||
ntag424_calc_mac(session_keys, apdu->ins, apdu->data, size, &apdu->data[size]);
|
||||
session_keys->command_counter++; // CmdCtr should be incremented each time a MAC is calculated
|
||||
apdu->lc = size + 8;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ntag424_comm_encrypt_apdu(APDU_t *apdu, int apdu_max_data_size, ntag424_session_keys_t *session_keys) {
|
||||
static int ntag424_comm_encrypt_apdu(APDU_t *apdu, int command_header_length, int apdu_max_data_size, ntag424_session_keys_t *session_keys) {
|
||||
// ------- Calculate IV
|
||||
uint8_t ivc[16];
|
||||
ntag424_calc_iv(session_keys, ivc);
|
||||
ntag424_calc_send_iv(session_keys, ivc);
|
||||
|
||||
int size = apdu->lc;
|
||||
|
||||
size_t encrypt_data_size = size - 1;
|
||||
size_t encrypt_data_size = size - command_header_length;
|
||||
size_t padded_data_size = encrypt_data_size + 16 - (encrypt_data_size % 16); // pad up to 16 byte blocks
|
||||
uint8_t temp_buffer[256] = {0};
|
||||
|
||||
if (padded_data_size + 1 > apdu_max_data_size) {
|
||||
if (!encrypt_data_size) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (padded_data_size + command_header_length > apdu_max_data_size) {
|
||||
return PM3_EOVFLOW;
|
||||
}
|
||||
|
||||
// ------ Pad data
|
||||
memcpy(temp_buffer, &apdu->data[1], encrypt_data_size); // We encrypt everything except the CmdHdr (first byte in data)
|
||||
memcpy(temp_buffer, &apdu->data[command_header_length], encrypt_data_size); // We encrypt everything except the CmdHdr (first byte in data)
|
||||
temp_buffer[encrypt_data_size] = 0x80;
|
||||
|
||||
// ------ Encrypt it
|
||||
aes_encode(ivc, session_keys->encryption, temp_buffer, &apdu->data[1], padded_data_size);
|
||||
aes_encode(ivc, session_keys->encryption, temp_buffer, &apdu->data[command_header_length], padded_data_size);
|
||||
|
||||
apdu->lc = (uint8_t)(1 + padded_data_size); // Set size to CmdHdr + padded data
|
||||
apdu->lc = (uint8_t)(command_header_length + padded_data_size); // Set size to CmdHdr + padded data
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ntag424_exchange_apdu(APDU_t *apdu, uint8_t *response, int *response_length, ntag424_communication_mode_t comm_mode, ntag424_session_keys_t *session_keys, uint8_t sw1_expected, uint8_t sw2_expected) {
|
||||
static int ntag424_exchange_apdu(APDU_t *apdu, int command_header_length, uint8_t *response, int *response_length, ntag424_communication_mode_t comm_mode, ntag424_session_keys_t *session_keys, uint8_t sw1_expected, uint8_t sw2_expected) {
|
||||
|
||||
int res;
|
||||
|
||||
|
@ -324,14 +306,14 @@ static int ntag424_exchange_apdu(APDU_t *apdu, uint8_t *response, int *response_
|
|||
}
|
||||
|
||||
if (comm_mode == COMM_FULL) {
|
||||
res = ntag424_comm_encrypt_apdu(apdu, buffer_length, session_keys);
|
||||
res = ntag424_comm_encrypt_apdu(apdu, command_header_length, buffer_length, session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (comm_mode == COMM_MAC || comm_mode == COMM_FULL) {
|
||||
res = ntag424_comm_mac_apdu(apdu, buffer_length, session_keys);
|
||||
res = ntag424_comm_mac_apdu(apdu, command_header_length, buffer_length, session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
@ -346,7 +328,7 @@ static int ntag424_exchange_apdu(APDU_t *apdu, uint8_t *response, int *response_
|
|||
|
||||
res = ExchangeAPDU14a(cmd, apdu_length + 1, false, true, response, *response_length, response_length);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Failed to exchange APDU");
|
||||
PrintAndLogEx(ERR, "Failed to exchange APDU: %d", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -363,8 +345,18 @@ static int ntag424_exchange_apdu(APDU_t *apdu, uint8_t *response, int *response_
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// TODO: In case of COMM_FULL we would need to decrypt response here as well.
|
||||
// And in case of COMM_MAC we would need to verify the MAC here, if we want to verify the card.
|
||||
// Decrypt data if we are in full communications mode. If we want to verify MAC, this
|
||||
// should also be done here
|
||||
if (comm_mode == COMM_FULL) {
|
||||
uint8_t iv[16] = {0};
|
||||
ntag424_calc_recieve_iv(session_keys, iv);
|
||||
|
||||
uint8_t tmp[256];
|
||||
memcpy(tmp, response, *response_length);
|
||||
aes_decode(iv, session_keys->encryption, response, tmp, *response_length - 10);
|
||||
|
||||
memcpy(response, tmp, *response_length);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -382,7 +374,7 @@ static int ntag424_get_file_settings(uint8_t fileno, ntag424_file_settings_t *se
|
|||
.extended_apdu = false
|
||||
};
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
int res = ntag424_exchange_apdu(&apdu, 1, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
@ -422,10 +414,7 @@ static int ntag424_write_file_settings(uint8_t fileno, ntag424_file_settings_t *
|
|||
int response_length = 8 + 2;
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_FULL, session_keys, 0x91, 0x00);
|
||||
|
||||
|
||||
session_keys->command_counter++; // Should this be incremented only on success?
|
||||
int res = ntag424_exchange_apdu(&apdu, 1, response, &response_length, COMM_FULL, session_keys, 0x91, 0x00);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -492,7 +481,7 @@ static int ntag424_auth_first_step(uint8_t keyno, uint8_t *key, uint8_t *out) {
|
|||
int response_length = 16 + 2;
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_PLAIN, NULL, 0x91, 0xAF);
|
||||
int res = ntag424_exchange_apdu(&apdu, 2, response, &response_length, COMM_PLAIN, NULL, 0x91, 0xAF);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
@ -518,7 +507,7 @@ static int ntag424_auth_second_step(uint8_t *challenge, uint8_t *response_out) {
|
|||
int response_length = 256;
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
int res = ntag424_exchange_apdu(&apdu, 0x20, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
@ -628,7 +617,7 @@ static int ntag424_authenticate_ev2_first(uint8_t keyno, uint8_t *key, ntag424_s
|
|||
|
||||
// Write file to card. Only supports plain communications mode. Authentication must be done
|
||||
// first unless file has free write access.
|
||||
static int ntag424_write_data(uint8_t fileno, uint16_t offset, uint16_t num_bytes, uint8_t *in) {
|
||||
static int ntag424_write_data(uint8_t fileno, uint16_t offset, uint16_t num_bytes, uint8_t *in, ntag424_communication_mode_t comm_mode, ntag424_session_keys_t *session_keys) {
|
||||
size_t remainder = 0;
|
||||
|
||||
// Split writes that are too large for one APDU
|
||||
|
@ -655,16 +644,16 @@ static int ntag424_write_data(uint8_t fileno, uint16_t offset, uint16_t num_byte
|
|||
.data = cmd,
|
||||
};
|
||||
|
||||
int response_length = 2;
|
||||
int response_length = 8 + 2; // potential MAC and result
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
int res = ntag424_exchange_apdu(&apdu, sizeof(cmd_header), response, &response_length, comm_mode, session_keys, 0x91, 0x00);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (remainder > 0) {
|
||||
return ntag424_write_data(fileno, offset + num_bytes, remainder, &in[num_bytes]);
|
||||
return ntag424_write_data(fileno, offset + num_bytes, remainder, &in[num_bytes], comm_mode, session_keys);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
@ -672,8 +661,8 @@ static int ntag424_write_data(uint8_t fileno, uint16_t offset, uint16_t num_byte
|
|||
|
||||
// Read file from card. Only supports plain communications mode. Authentication must be done
|
||||
// first unless file has free read access.
|
||||
static int ntag424_read_data(uint8_t fileno, uint16_t offset, uint16_t num_bytes, uint8_t *out) {
|
||||
uint8_t cmd[] = {
|
||||
static int ntag424_read_data(uint8_t fileno, uint16_t offset, uint16_t num_bytes, uint8_t *out, ntag424_communication_mode_t comm_mode, ntag424_session_keys_t *session_keys) {
|
||||
uint8_t cmd_header[] = {
|
||||
fileno,
|
||||
(uint8_t)offset, (uint8_t)(offset << 8), (uint8_t)(offset << 16), // offset
|
||||
(uint8_t)num_bytes, (uint8_t)(num_bytes >> 8), 0x00
|
||||
|
@ -682,14 +671,14 @@ static int ntag424_read_data(uint8_t fileno, uint16_t offset, uint16_t num_bytes
|
|||
APDU_t apdu = {
|
||||
.cla = 0x90,
|
||||
.ins = NTAG424_CMD_READ_DATA,
|
||||
.lc = sizeof(cmd),
|
||||
.data = cmd,
|
||||
.lc = sizeof(cmd_header),
|
||||
.data = cmd_header,
|
||||
};
|
||||
|
||||
int response_length = num_bytes + 2;
|
||||
int response_length = num_bytes + 4 + 2 + 20; // number of bytes to read + mac + result + potential padding
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_PLAIN, NULL, 0x91, 0x00);
|
||||
int res = ntag424_exchange_apdu(&apdu, sizeof(cmd_header), response, &response_length, comm_mode, session_keys, 0x91, 0x00);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
@ -734,12 +723,47 @@ static int ntag424_change_key(uint8_t keyno, uint8_t *new_key, uint8_t *old_key,
|
|||
int response_length = 8 + 2;
|
||||
uint8_t response[response_length];
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, response, &response_length, COMM_FULL, session_keys, 0x91, 0x00);
|
||||
|
||||
session_keys->command_counter++; // Should this be incremented only on success?
|
||||
|
||||
int res = ntag424_exchange_apdu(&apdu, 1, response, &response_length, COMM_FULL, session_keys, 0x91, 0x00);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int CmdHF_ntag424_view(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf ntag424 view",
|
||||
"Print a NTAG 424 DNA dump file (bin/eml/json)",
|
||||
"hf ntag424 view -f hf-ntag424-01020304-dump.bin"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
|
||||
arg_lit0("v", "verbose", "Verbose output"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE];
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// read dump file
|
||||
uint8_t *dump = NULL;
|
||||
size_t bytes_read = NTAG424_MAX_BYTES;
|
||||
int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, NTAG424_MAX_BYTES);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
|
||||
PrintAndLogEx(INFO, "File size %zu bytes", bytes_read);
|
||||
}
|
||||
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF_ntag424_info(const char *Cmd) {
|
||||
|
@ -769,7 +793,6 @@ static int ntag424_cli_get_auth_information(CLIParserContext *ctx, int key_no_in
|
|||
CLIGetHexWithReturn(ctx, key_index, key, &keylen);
|
||||
|
||||
if (keylen != 16) {
|
||||
PrintAndLogEx(ERR, "Key must be 16 bytes");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -840,6 +863,7 @@ static int CmdHF_ntag424_read(const char *Cmd) {
|
|||
arg_str0("k", "key", "<hex>", "Key for authentication (HEX 16 bytes)"),
|
||||
arg_int0("o", "offset", "<dec>", "Offset to read in file (default 0)"),
|
||||
arg_int1("l", "length", "<dec>", "Number of bytes to read"),
|
||||
arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -851,10 +875,20 @@ static int CmdHF_ntag424_read(const char *Cmd) {
|
|||
int fileno = arg_get_int(ctx, 1);
|
||||
|
||||
if (ntag424_cli_get_auth_information(ctx, 2, 3, &keyno, key) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Reading unauthenticated");
|
||||
auth = 0;
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Reading authenticated");
|
||||
}
|
||||
|
||||
ntag424_communication_mode_t comm_mode;
|
||||
int comm_out = 0;
|
||||
if (CLIGetOptionList(arg_get_str(ctx, 6), ntag424_communication_mode_options, &comm_out)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
comm_mode = comm_out;
|
||||
|
||||
if (comm_mode != COMM_PLAIN && auth == 0) {
|
||||
PrintAndLogEx(ERR, "Only plain communication mode can be used without a key specified");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int offset = arg_get_int_def(ctx, 4, 0);
|
||||
|
@ -875,8 +909,9 @@ static int CmdHF_ntag424_read(const char *Cmd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
ntag424_session_keys_t session_keys;
|
||||
if (auth) {
|
||||
res = ntag424_authenticate_ev2_first(keyno, key, NULL);
|
||||
res = ntag424_authenticate_ev2_first(keyno, key, &session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Failed to authenticate with key %d", keyno);
|
||||
DropField();
|
||||
|
@ -888,7 +923,7 @@ static int CmdHF_ntag424_read(const char *Cmd) {
|
|||
|
||||
uint8_t data[512];
|
||||
|
||||
res = ntag424_read_data(fileno, offset, read_length, data);
|
||||
res = ntag424_read_data(fileno, offset, read_length, data, comm_mode, &session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
DropField();
|
||||
return res;
|
||||
|
@ -915,6 +950,7 @@ static int CmdHF_ntag424_write(const char *Cmd) {
|
|||
arg_str0("k", "key", "<hex>", "Key for authentication (HEX 16 bytes)"),
|
||||
arg_int0("o", "offset", "<dec>", "Offset to write in file (default 0)"),
|
||||
arg_str1("d", "data", "<hex>", "Data to write"),
|
||||
arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -926,10 +962,20 @@ static int CmdHF_ntag424_write(const char *Cmd) {
|
|||
int fileno = arg_get_int(ctx, 1);
|
||||
|
||||
if (ntag424_cli_get_auth_information(ctx, 2, 3, &keyno, key) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Will write unauthenticated");
|
||||
auth = 0;
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Will write authenticated");
|
||||
}
|
||||
|
||||
ntag424_communication_mode_t comm_mode;
|
||||
int comm_out = 0;
|
||||
if (CLIGetOptionList(arg_get_str(ctx, 6), ntag424_communication_mode_options, &comm_out)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
comm_mode = comm_out;
|
||||
|
||||
if (comm_mode != COMM_PLAIN && auth == 0) {
|
||||
PrintAndLogEx(ERR, "Only plain communication mode can be used without a key specified");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int offset = arg_get_int_def(ctx, 4, 0);
|
||||
|
@ -953,8 +999,9 @@ static int CmdHF_ntag424_write(const char *Cmd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
ntag424_session_keys_t session_keys;
|
||||
if (auth) {
|
||||
res = ntag424_authenticate_ev2_first(keyno, key, NULL);
|
||||
res = ntag424_authenticate_ev2_first(keyno, key, &session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Failed to authenticate with key %d", keyno);
|
||||
DropField();
|
||||
|
@ -964,7 +1011,7 @@ static int CmdHF_ntag424_write(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
res = ntag424_write_data(fileno, offset, datalen, data);
|
||||
res = ntag424_write_data(fileno, offset, datalen, data, comm_mode, &session_keys);
|
||||
if (res != PM3_SUCCESS) {
|
||||
DropField();
|
||||
return res;
|
||||
|
|
|
@ -6887,9 +6887,10 @@
|
|||
"-n, --keyno <dec> Key number",
|
||||
"-k, --key <hex> Key for authentication (HEX 16 bytes)",
|
||||
"-o, --offset <dec> Offset to read in file (default 0)",
|
||||
"-l, --length <dec> Number of bytes to read"
|
||||
"-l, --length <dec> Number of bytes to read",
|
||||
"-m, --cmode <plain|mac|encrypt> Communicaton mode"
|
||||
],
|
||||
"usage": "hf ntag424 read [-h] -f <dec> [-n <dec>] [-k <hex>] [-o <dec>] -l <dec>"
|
||||
"usage": "hf ntag424 read [-h] -f <dec> [-n <dec>] [-k <hex>] [-o <dec>] -l <dec> [-m <plain|mac|encrypt>]"
|
||||
},
|
||||
"hf ntag424 view": {
|
||||
"command": "hf ntag424 view",
|
||||
|
@ -6918,9 +6919,10 @@
|
|||
"-n, --keyno <dec> Key number",
|
||||
"-k, --key <hex> Key for authentication (HEX 16 bytes)",
|
||||
"-o, --offset <dec> Offset to write in file (default 0)",
|
||||
"-d, --data <hex> Data to write"
|
||||
"-d, --data <hex> Data to write",
|
||||
"-m, --cmode <plain|mac|encrypt> Communicaton mode"
|
||||
],
|
||||
"usage": "hf ntag424 write [-h] -f <dec> [-n <dec>] [-k <hex>] [-o <dec>] -d <hex>"
|
||||
"usage": "hf ntag424 write [-h] -f <dec> [-n <dec>] [-k <hex>] [-o <dec>] -d <hex> [-m <plain|mac|encrypt>]"
|
||||
},
|
||||
"hf plot": {
|
||||
"command": "hf plot",
|
||||
|
@ -12012,6 +12014,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 696,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2023-10-29T12:42:07"
|
||||
"extracted_on": "2023-10-29T15:43:05"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue