mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-28 03:59:58 -07:00
OFW PR 2783: SLIX2 emulation support
by g3gg0
This commit is contained in:
@@ -9,6 +9,120 @@
|
||||
|
||||
#define TAG "SLIX"
|
||||
|
||||
ReturnCode slix2_read_nxp_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data);
|
||||
|
||||
uint8_t rxBuf[32];
|
||||
uint16_t received = 0;
|
||||
ReturnCode ret = ERR_NONE;
|
||||
|
||||
FURI_LOG_D(TAG, "Read NXP SYSTEM INFORMATION...");
|
||||
|
||||
for(int tries = 0; tries < NFCV_COMMAND_RETRIES; tries++) {
|
||||
uint8_t cmd[] = {};
|
||||
uint8_t uid[NFCV_UID_LENGTH];
|
||||
|
||||
/* UID is stored reversed in requests */
|
||||
for(int pos = 0; pos < nfc_data->uid_len; pos++) {
|
||||
uid[pos] = nfc_data->uid[nfc_data->uid_len - 1 - pos];
|
||||
}
|
||||
|
||||
ReturnCode ret = rfalNfcvPollerTransceiveReq(
|
||||
NFCV_CMD_NXP_GET_NXP_SYSTEM_INFORMATION,
|
||||
RFAL_NFCV_REQ_FLAG_DEFAULT,
|
||||
NFCV_MANUFACTURER_NXP,
|
||||
uid,
|
||||
cmd,
|
||||
sizeof(cmd),
|
||||
rxBuf,
|
||||
sizeof(rxBuf),
|
||||
&received);
|
||||
|
||||
if(ret == ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret != ERR_NONE || received != 8) {
|
||||
FURI_LOG_D(TAG, "Failed: %d, %d", ret, received);
|
||||
return ret;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Success...");
|
||||
|
||||
NfcVSlixData* slix = &nfcv_data->sub_data.slix;
|
||||
slix->pp_pointer = rxBuf[1];
|
||||
slix->pp_condition = rxBuf[2];
|
||||
|
||||
/* convert NXP's to our internal lock bits format */
|
||||
nfcv_data->security_status[0] = 0;
|
||||
nfcv_data->security_status[0] |= (rxBuf[3] & SlixLockBitDsfid) ? NfcVLockBitDsfid : 0;
|
||||
nfcv_data->security_status[0] |= (rxBuf[3] & SlixLockBitAfi) ? NfcVLockBitAfi : 0;
|
||||
nfcv_data->security_status[0] |= (rxBuf[3] & SlixLockBitEas) ? NfcVLockBitEas : 0;
|
||||
nfcv_data->security_status[0] |= (rxBuf[3] & SlixLockBitPpl) ? NfcVLockBitPpl : 0;
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
ReturnCode slix2_read_signature(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data);
|
||||
|
||||
uint8_t rxBuf[64];
|
||||
uint16_t received = 0;
|
||||
ReturnCode ret = ERR_NONE;
|
||||
|
||||
FURI_LOG_D(TAG, "Read SIGNATURE...");
|
||||
|
||||
for(int tries = 0; tries < NFCV_COMMAND_RETRIES; tries++) {
|
||||
uint8_t cmd[] = {};
|
||||
uint8_t uid[NFCV_UID_LENGTH];
|
||||
|
||||
/* UID is stored reversed in requests */
|
||||
for(int pos = 0; pos < nfc_data->uid_len; pos++) {
|
||||
uid[pos] = nfc_data->uid[nfc_data->uid_len - 1 - pos];
|
||||
}
|
||||
|
||||
ReturnCode ret = rfalNfcvPollerTransceiveReq(
|
||||
NFCV_CMD_NXP_READ_SIGNATURE,
|
||||
RFAL_NFCV_REQ_FLAG_DEFAULT,
|
||||
NFCV_MANUFACTURER_NXP,
|
||||
uid,
|
||||
cmd,
|
||||
sizeof(cmd),
|
||||
rxBuf,
|
||||
sizeof(rxBuf),
|
||||
&received);
|
||||
|
||||
if(ret == ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret != ERR_NONE || received != 33) {
|
||||
FURI_LOG_D(TAG, "Failed: %d, %d", ret, received);
|
||||
return ret;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Success...");
|
||||
|
||||
NfcVSlixData* slix = &nfcv_data->sub_data.slix;
|
||||
memcpy(slix->signature, &rxBuf[1], 32);
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
ReturnCode slix2_read_custom(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||
ReturnCode ret = ERR_NONE;
|
||||
|
||||
ret = slix2_read_nxp_sysinfo(nfc_data, nfcv_data);
|
||||
if(ret != ERR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
ret = slix2_read_signature(nfc_data, nfcv_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t slix_read_be(uint8_t* data, uint32_t length) {
|
||||
uint32_t value = 0;
|
||||
|
||||
@@ -137,6 +251,43 @@ ReturnCode slix_unlock(NfcVData* data, uint32_t password_id) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void slix_generic_pass_infos(
|
||||
uint8_t password_id,
|
||||
NfcVSlixData* slix,
|
||||
uint8_t** password,
|
||||
uint32_t* flag_valid,
|
||||
uint32_t* flag_set) {
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
*password = slix->key_read;
|
||||
*flag_valid = NfcVSlixDataFlagsValidKeyRead;
|
||||
*flag_set = NfcVSlixDataFlagsHasKeyRead;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
*password = slix->key_write;
|
||||
*flag_valid = NfcVSlixDataFlagsValidKeyWrite;
|
||||
*flag_set = NfcVSlixDataFlagsHasKeyWrite;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
*password = slix->key_privacy;
|
||||
*flag_valid = NfcVSlixDataFlagsValidKeyPrivacy;
|
||||
*flag_set = NfcVSlixDataFlagsHasKeyPrivacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
*password = slix->key_destroy;
|
||||
*flag_valid = NfcVSlixDataFlagsValidKeyDestroy;
|
||||
*flag_set = NfcVSlixDataFlagsHasKeyDestroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
*password = slix->key_eas;
|
||||
*flag_valid = NfcVSlixDataFlagsValidKeyEas;
|
||||
*flag_set = NfcVSlixDataFlagsHasKeyEas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool slix_generic_protocol_filter(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FuriHalNfcDevData* nfc_data,
|
||||
@@ -150,7 +301,8 @@ bool slix_generic_protocol_filter(
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
NfcVSlixData* slix = &nfcv_data->sub_data.slix;
|
||||
|
||||
if(slix->privacy && ctx->command != NFCV_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||
if((slix->flags & NfcVSlixDataFlagsPrivacy) &&
|
||||
ctx->command != NFCV_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||
ctx->command != NFCV_CMD_NXP_SET_PASSWORD) {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
@@ -186,66 +338,73 @@ bool slix_generic_protocol_filter(
|
||||
}
|
||||
|
||||
case NFCV_CMD_NXP_SET_PASSWORD: {
|
||||
/* the password to be set is the first parameter */
|
||||
uint8_t password_id = nfcv_data->frame[ctx->payload_offset];
|
||||
/* right after that is the XORed password */
|
||||
uint8_t* password_xored = &nfcv_data->frame[ctx->payload_offset + 1];
|
||||
|
||||
/* only handle if the password type is supported */
|
||||
if(!(password_id & password_supported)) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t* password_xored = &nfcv_data->frame[ctx->payload_offset + 1];
|
||||
/* fetch the last RAND value */
|
||||
uint8_t* rand = slix->rand;
|
||||
uint8_t* password = NULL;
|
||||
|
||||
/* first calc the password that has been sent */
|
||||
uint8_t password_rcv[4];
|
||||
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
password = slix->key_read;
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
password = slix->key_write;
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
password = slix->key_privacy;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
password = slix->key_destroy;
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
password = slix->key_eas;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
for(int pos = 0; pos < 4; pos++) {
|
||||
password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2];
|
||||
}
|
||||
uint32_t pass_received = slix_read_be(password_rcv, 4);
|
||||
|
||||
/* then determine the password type (or even update if not set yet) */
|
||||
uint8_t* password = NULL;
|
||||
uint32_t flag_valid = 0;
|
||||
uint32_t flag_set = 0;
|
||||
|
||||
slix_generic_pass_infos(password_id, slix, &password, &flag_valid, &flag_set);
|
||||
|
||||
/* when the password is not supported, return silently */
|
||||
if(!password) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(int pos = 0; pos < 4; pos++) {
|
||||
password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2];
|
||||
}
|
||||
uint32_t pass_expect = slix_read_be(password, 4);
|
||||
uint32_t pass_received = slix_read_be(password_rcv, 4);
|
||||
/* check if the password is known */
|
||||
bool pass_valid = false;
|
||||
uint32_t pass_expect = 0;
|
||||
|
||||
/* if the password is all-zeroes, just accept any password*/
|
||||
if(!pass_expect || pass_expect == pass_received) {
|
||||
if(slix->flags & flag_set) {
|
||||
/* if so, fetch the stored password and compare */
|
||||
pass_expect = slix_read_be(password, 4);
|
||||
pass_valid = (pass_expect == pass_received);
|
||||
} else {
|
||||
/* if not known, just accept it and store that password */
|
||||
memcpy(password, password_rcv, 4);
|
||||
nfcv_data->modified = true;
|
||||
slix->flags |= flag_set;
|
||||
|
||||
pass_valid = true;
|
||||
}
|
||||
|
||||
/* if the pass was valid or accepted for other reasons, continue */
|
||||
if(pass_valid) {
|
||||
slix->flags |= flag_valid;
|
||||
|
||||
/* handle actions when a correct password was given, aside of setting the flag */
|
||||
switch(password_id) {
|
||||
case SLIX_PASS_READ:
|
||||
break;
|
||||
case SLIX_PASS_WRITE:
|
||||
break;
|
||||
case SLIX_PASS_PRIVACY:
|
||||
slix->privacy = false;
|
||||
slix->flags &= ~NfcVSlixDataFlagsPrivacy;
|
||||
nfcv_data->modified = true;
|
||||
break;
|
||||
case SLIX_PASS_DESTROY:
|
||||
slix->flags |= NfcVSlixDataFlagsDestroyed;
|
||||
FURI_LOG_D(TAG, "Pooof! Got destroyed");
|
||||
break;
|
||||
case SLIX_PASS_EASAFI:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->response_buffer[0] = NFCV_NOERROR;
|
||||
nfcv_emu_send(
|
||||
tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time);
|
||||
@@ -268,6 +427,49 @@ bool slix_generic_protocol_filter(
|
||||
break;
|
||||
}
|
||||
|
||||
case NFCV_CMD_NXP_WRITE_PASSWORD: {
|
||||
uint8_t password_id = nfcv_data->frame[ctx->payload_offset];
|
||||
|
||||
if(!(password_id & password_supported)) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t* new_password = &nfcv_data->frame[ctx->payload_offset + 1];
|
||||
uint8_t* password = NULL;
|
||||
uint32_t flag_valid = 0;
|
||||
uint32_t flag_set = 0;
|
||||
|
||||
slix_generic_pass_infos(password_id, slix, &password, &flag_valid, &flag_set);
|
||||
|
||||
/* when the password is not supported, return silently */
|
||||
if(!password) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool pass_valid = (slix->flags & flag_valid);
|
||||
if(!(slix->flags & flag_set)) {
|
||||
pass_valid = true;
|
||||
}
|
||||
|
||||
if(pass_valid) {
|
||||
slix->flags |= flag_valid;
|
||||
slix->flags |= flag_set;
|
||||
|
||||
memcpy(password, new_password, 4);
|
||||
|
||||
ctx->response_buffer[0] = NFCV_NOERROR;
|
||||
nfcv_emu_send(
|
||||
tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time);
|
||||
snprintf(
|
||||
nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_PASSWORD OK");
|
||||
} else {
|
||||
snprintf(
|
||||
nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_PASSWORD FAIL");
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NFCV_CMD_NXP_ENABLE_PRIVACY: {
|
||||
ctx->response_buffer[0] = NFCV_NOERROR;
|
||||
|
||||
@@ -278,7 +480,7 @@ bool slix_generic_protocol_filter(
|
||||
sizeof(nfcv_data->last_command),
|
||||
"NFCV_CMD_NXP_ENABLE_PRIVACY");
|
||||
|
||||
slix->privacy = true;
|
||||
slix->flags |= NfcVSlixDataFlagsPrivacy;
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
@@ -315,7 +517,10 @@ void slix_l_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" Privacy mode: %s",
|
||||
(nfcv_data->sub_data.slix.flags & NfcVSlixDataFlagsPrivacy) ? "ON" : "OFF");
|
||||
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
ctx->emu_protocol_filter = &slix_l_protocol_filter;
|
||||
@@ -345,7 +550,10 @@ void slix_s_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" Privacy mode: %s",
|
||||
(nfcv_data->sub_data.slix.flags & NfcVSlixDataFlagsPrivacy) ? "ON" : "OFF");
|
||||
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
ctx->emu_protocol_filter = &slix_s_protocol_filter;
|
||||
@@ -375,7 +583,10 @@ void slix_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" Privacy mode: %s",
|
||||
(nfcv_data->sub_data.slix.flags & NfcVSlixDataFlagsPrivacy) ? "ON" : "OFF");
|
||||
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
ctx->emu_protocol_filter = &slix_protocol_filter;
|
||||
@@ -389,6 +600,10 @@ bool slix2_protocol_filter( // -V524
|
||||
furi_assert(nfc_data);
|
||||
furi_assert(nfcv_data_in);
|
||||
|
||||
NfcVData* nfcv_data = (NfcVData*)nfcv_data_in;
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
NfcVSlixData* slix = &nfcv_data->sub_data.slix;
|
||||
|
||||
bool handled = false;
|
||||
|
||||
/* many SLIX share some of the functions, place that in a generic handler */
|
||||
@@ -396,6 +611,157 @@ bool slix2_protocol_filter( // -V524
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(ctx->command) {
|
||||
/* override WRITE BLOCK for block 79 (16 bit counter) */
|
||||
case NFCV_CMD_WRITE_BLOCK:
|
||||
case NFCV_CMD_WRITE_MULTI_BLOCK: {
|
||||
uint8_t resp_len = 1;
|
||||
uint8_t blocks = 1;
|
||||
uint8_t block = nfcv_data->frame[ctx->payload_offset];
|
||||
uint8_t data_pos = ctx->payload_offset + 1;
|
||||
|
||||
if(ctx->command == NFCV_CMD_WRITE_MULTI_BLOCK) {
|
||||
blocks = nfcv_data->frame[data_pos] + 1;
|
||||
data_pos++;
|
||||
}
|
||||
|
||||
uint8_t* data = &nfcv_data->frame[data_pos];
|
||||
uint32_t data_len = nfcv_data->block_size * blocks;
|
||||
|
||||
if((block + blocks) <= nfcv_data->block_num &&
|
||||
(data_pos + data_len + 2) == nfcv_data->frame_length) {
|
||||
ctx->response_buffer[0] = NFCV_NOERROR;
|
||||
|
||||
for(int block_num = block; block_num < block + blocks; block_num++) {
|
||||
/* special case, 16-bit counter */
|
||||
if(block_num == 79) {
|
||||
uint32_t dest;
|
||||
uint32_t ctr_old;
|
||||
|
||||
memcpy(&dest, &nfcv_data->frame[data_pos], 4);
|
||||
memcpy(&ctr_old, &nfcv_data->data[nfcv_data->block_size * block_num], 4);
|
||||
|
||||
uint32_t ctr_new = ctr_old;
|
||||
bool allowed = true;
|
||||
|
||||
/* increment counter */
|
||||
if(dest == 1) {
|
||||
ctr_new = (ctr_old & 0xFFFF0000) | ((ctr_old + 1) & 0xFFFF);
|
||||
|
||||
/* protection flag set? */
|
||||
if(ctr_old & 0x01000000) {
|
||||
allowed = nfcv_data->sub_data.slix.flags &
|
||||
NfcVSlixDataFlagsValidKeyRead;
|
||||
}
|
||||
} else {
|
||||
ctr_new = dest;
|
||||
allowed = nfcv_data->sub_data.slix.flags & NfcVSlixDataFlagsValidKeyWrite;
|
||||
}
|
||||
|
||||
if(allowed) {
|
||||
memcpy(&nfcv_data->data[nfcv_data->block_size * block_num], &ctr_new, 4);
|
||||
} else {
|
||||
/* incorrect read or write password */
|
||||
ctx->response_buffer[0] = NFCV_RES_FLAG_ERROR;
|
||||
ctx->response_buffer[1] = NFCV_ERROR_GENERIC;
|
||||
resp_len = 2;
|
||||
}
|
||||
} else {
|
||||
memcpy(
|
||||
&nfcv_data->data[nfcv_data->block_size * block_num],
|
||||
&nfcv_data->frame[data_pos],
|
||||
nfcv_data->block_size);
|
||||
}
|
||||
data_pos += nfcv_data->block_size;
|
||||
}
|
||||
nfcv_data->modified = true;
|
||||
|
||||
} else {
|
||||
ctx->response_buffer[0] = NFCV_RES_FLAG_ERROR;
|
||||
ctx->response_buffer[1] = NFCV_ERROR_GENERIC;
|
||||
resp_len = 2;
|
||||
}
|
||||
|
||||
bool respond = (ctx->response_buffer[0] == NFCV_NOERROR) ||
|
||||
(ctx->addressed || ctx->selected);
|
||||
|
||||
if(respond) {
|
||||
nfcv_emu_send(
|
||||
tx_rx,
|
||||
nfcv_data,
|
||||
ctx->response_buffer,
|
||||
resp_len,
|
||||
ctx->response_flags,
|
||||
ctx->send_time);
|
||||
}
|
||||
|
||||
if(ctx->command == NFCV_CMD_WRITE_MULTI_BLOCK) {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"WRITE MULTI BLOCK %d, %d blocks",
|
||||
block,
|
||||
blocks);
|
||||
} else {
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"WRITE BLOCK %d <- %02X %02X %02X %02X",
|
||||
block,
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
data[3]);
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NFCV_CMD_NXP_READ_SIGNATURE: {
|
||||
uint32_t len = 0;
|
||||
ctx->response_buffer[len++] = NFCV_NOERROR;
|
||||
memcpy(&ctx->response_buffer[len], slix->signature, sizeof(slix->signature));
|
||||
len += sizeof(slix->signature);
|
||||
|
||||
nfcv_emu_send(
|
||||
tx_rx, nfcv_data, ctx->response_buffer, len, ctx->response_flags, ctx->send_time);
|
||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ_SIGNATURE");
|
||||
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NFCV_CMD_NXP_GET_NXP_SYSTEM_INFORMATION: {
|
||||
uint32_t len = 0;
|
||||
uint8_t lock_bits = 0;
|
||||
|
||||
/* convert our internal lock bits format into NXP's */
|
||||
lock_bits |= (nfcv_data->security_status[0] & NfcVLockBitDsfid) ? SlixLockBitDsfid : 0;
|
||||
lock_bits |= (nfcv_data->security_status[0] & NfcVLockBitAfi) ? SlixLockBitAfi : 0;
|
||||
lock_bits |= (nfcv_data->security_status[0] & NfcVLockBitEas) ? SlixLockBitEas : 0;
|
||||
lock_bits |= (nfcv_data->security_status[0] & NfcVLockBitPpl) ? SlixLockBitPpl : 0;
|
||||
|
||||
ctx->response_buffer[len++] = NFCV_NOERROR;
|
||||
ctx->response_buffer[len++] = nfcv_data->sub_data.slix.pp_pointer;
|
||||
ctx->response_buffer[len++] = nfcv_data->sub_data.slix.pp_condition;
|
||||
ctx->response_buffer[len++] = lock_bits;
|
||||
ctx->response_buffer[len++] = 0x7F; /* features LSB */
|
||||
ctx->response_buffer[len++] = 0x35; /* features */
|
||||
ctx->response_buffer[len++] = 0; /* features */
|
||||
ctx->response_buffer[len++] = 0; /* features MSB */
|
||||
|
||||
nfcv_emu_send(
|
||||
tx_rx, nfcv_data, ctx->response_buffer, len, ctx->response_flags, ctx->send_time);
|
||||
snprintf(
|
||||
nfcv_data->last_command,
|
||||
sizeof(nfcv_data->last_command),
|
||||
"GET_NXP_SYSTEM_INFORMATION");
|
||||
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -405,7 +771,10 @@ void slix2_prepare(NfcVData* nfcv_data) {
|
||||
FURI_LOG_D(
|
||||
TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4));
|
||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4));
|
||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF");
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" Privacy mode: %s",
|
||||
(nfcv_data->sub_data.slix.flags & NfcVSlixDataFlagsPrivacy) ? "ON" : "OFF");
|
||||
|
||||
NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx;
|
||||
ctx->emu_protocol_filter = &slix2_protocol_filter;
|
||||
|
||||
Reference in New Issue
Block a user