mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
NFC: ISO 15693-3 emulation READ_MULTI and GET_BLOCK_SECURITY fixes (#501)
* Fix ISO15693 crash (hopefully) * NFC: Fix off-by-one block count in ISO 15693-3 READ MULTI command * NFC: Handle 256 long BLOCK SECURITY response and too large READ MULTI response * Move the define so correlation is clearer * Oops * Change to no reply if too many blocks requested than can be handled * Update CHANGELOG.md --------- Co-authored-by: WillyJL <me@willyjl.dev>
This commit is contained in:
@@ -42,6 +42,7 @@
|
|||||||
- UL: Nice Flor S remove extra uint64 variable (by @xMasterX)
|
- UL: Nice Flor S remove extra uint64 variable (by @xMasterX)
|
||||||
- NFC:
|
- NFC:
|
||||||
- Fix sending 32+ byte ISO 15693-3 commands (by @WillyJL)
|
- Fix sending 32+ byte ISO 15693-3 commands (by @WillyJL)
|
||||||
|
- Fixes to `READ_MULTI` and `GET_BLOCK_SECURITY` commands in ISO 15693-3 emulation (#501 by @WillyJL & aaronjamt)
|
||||||
- UL: Fix LED not blinking at SLIX unlock (by @xMasterX)
|
- UL: Fix LED not blinking at SLIX unlock (by @xMasterX)
|
||||||
- UL: UI: Some small changes (by @xMasterX)
|
- UL: UI: Some small changes (by @xMasterX)
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
#include <digital_signal/digital_sequence.h>
|
#include <digital_signal/digital_sequence.h>
|
||||||
|
|
||||||
|
#include <nfc/protocols/iso15693_3/iso15693_3_listener_i.h>
|
||||||
|
|
||||||
#define BITS_IN_BYTE (8U)
|
#define BITS_IN_BYTE (8U)
|
||||||
|
|
||||||
|
#define ISO15693_SIGNAL_BUFFER_SIZE (ISO15693_3_LISTENER_BUFFER_SIZE * BITS_IN_BYTE + 2)
|
||||||
|
|
||||||
#define ISO15693_SIGNAL_COEFF_HI (1U)
|
#define ISO15693_SIGNAL_COEFF_HI (1U)
|
||||||
#define ISO15693_SIGNAL_COEFF_LO (4U)
|
#define ISO15693_SIGNAL_COEFF_LO (4U)
|
||||||
|
|
||||||
@@ -151,7 +155,7 @@ Iso15693Signal* iso15693_signal_alloc(const GpioPin* pin) {
|
|||||||
|
|
||||||
Iso15693Signal* instance = malloc(sizeof(Iso15693Signal));
|
Iso15693Signal* instance = malloc(sizeof(Iso15693Signal));
|
||||||
|
|
||||||
instance->tx_sequence = digital_sequence_alloc(BITS_IN_BYTE * 255 + 2, pin);
|
instance->tx_sequence = digital_sequence_alloc(ISO15693_SIGNAL_BUFFER_SIZE, pin);
|
||||||
|
|
||||||
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
||||||
iso15693_signal_bank_fill(instance, i);
|
iso15693_signal_bank_fill(instance, i);
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#define TAG "Iso15693_3Listener"
|
#define TAG "Iso15693_3Listener"
|
||||||
|
|
||||||
#define ISO15693_3_LISTENER_BUFFER_SIZE (256U)
|
|
||||||
|
|
||||||
Iso15693_3Listener* iso15693_3_listener_alloc(Nfc* nfc, Iso15693_3Data* data) {
|
Iso15693_3Listener* iso15693_3_listener_alloc(Nfc* nfc, Iso15693_3Data* data) {
|
||||||
furi_assert(nfc);
|
furi_assert(nfc);
|
||||||
|
|
||||||
|
|||||||
@@ -263,8 +263,9 @@ static Iso15693_3Error iso15693_3_listener_read_multi_blocks_handler(
|
|||||||
|
|
||||||
const uint32_t block_index_start = request->first_block_num;
|
const uint32_t block_index_start = request->first_block_num;
|
||||||
const uint32_t block_index_end =
|
const uint32_t block_index_end =
|
||||||
MIN((block_index_start + request->block_count + 1),
|
MIN((block_index_start + request->block_count),
|
||||||
((uint32_t)instance->data->system_info.block_count - 1));
|
((uint32_t)instance->data->system_info.block_count - 1));
|
||||||
|
const uint32_t block_count = block_index_end - block_index_start + 1;
|
||||||
|
|
||||||
error = iso15693_3_listener_extension_handler(
|
error = iso15693_3_listener_extension_handler(
|
||||||
instance,
|
instance,
|
||||||
@@ -273,8 +274,21 @@ static Iso15693_3Error iso15693_3_listener_read_multi_blocks_handler(
|
|||||||
(uint32_t)block_index_end);
|
(uint32_t)block_index_end);
|
||||||
if(error != Iso15693_3ErrorNone) break;
|
if(error != Iso15693_3ErrorNone) break;
|
||||||
|
|
||||||
|
const bool include_block_security = (flags & ISO15693_3_REQ_FLAG_T4_OPTION) != 0;
|
||||||
|
const uint8_t bytes_per_block =
|
||||||
|
(include_block_security ? 1 : 0) + instance->data->system_info.block_size;
|
||||||
|
const uint32_t response_data_max =
|
||||||
|
bit_buffer_get_capacity_bytes(instance->tx_buffer) - 1 - 2; // Flags and CRC
|
||||||
|
const uint32_t response_blocks_max = response_data_max / bytes_per_block;
|
||||||
|
if(block_count > response_blocks_max) {
|
||||||
|
// Tested on SLIX2, if asked for more blocks than supported at once there is no reply
|
||||||
|
// Let's do the same
|
||||||
|
error = Iso15693_3ErrorIgnore;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for(uint32_t i = block_index_start; i <= block_index_end; ++i) {
|
for(uint32_t i = block_index_start; i <= block_index_end; ++i) {
|
||||||
if(flags & ISO15693_3_REQ_FLAG_T4_OPTION) {
|
if(include_block_security) {
|
||||||
iso15693_3_append_block_security(
|
iso15693_3_append_block_security(
|
||||||
instance->data, i, instance->tx_buffer); // Block security (optional)
|
instance->data, i, instance->tx_buffer); // Block security (optional)
|
||||||
}
|
}
|
||||||
@@ -341,7 +355,7 @@ static Iso15693_3Error iso15693_3_listener_write_multi_blocks_handler(
|
|||||||
|
|
||||||
if(error != Iso15693_3ErrorNone) break;
|
if(error != Iso15693_3ErrorNone) break;
|
||||||
|
|
||||||
for(uint32_t i = block_index_start; i < block_count + request->first_block_num; ++i) {
|
for(uint32_t i = block_index_start; i <= block_index_end; ++i) {
|
||||||
const uint8_t* block_data = &request->block_data[block_size * i];
|
const uint8_t* block_data = &request->block_data[block_size * i];
|
||||||
iso15693_3_set_block_data(instance->data, i, block_data, block_size);
|
iso15693_3_set_block_data(instance->data, i, block_data, block_size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Based on GET_BLOCKS_SECURITY, one of the commands with lengthier responses:
|
||||||
|
// - 1 byte flags
|
||||||
|
// - 1 byte security status * 256 max block count
|
||||||
|
// - 2 byte crc
|
||||||
|
// for a response size of 259 bytes.
|
||||||
|
// There is also READ_MULTI_BLOCKS which has no explicit limit on requested block count
|
||||||
|
// and ISO 15693-3 also does not specify a maximum overall response length, so this command could
|
||||||
|
// theoretically result in a 8195 byte response (1 byte flags + 32 byte block * 256 blocks + 2 byte crc);
|
||||||
|
// for practicality we use a sufficient buffer for a full GET_BLOCKS_SECURITY and
|
||||||
|
// limit READ_MULTI_BLOCKS to how many blocks we can fit into that buffer size.
|
||||||
|
#define ISO15693_3_LISTENER_BUFFER_SIZE (259U)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
Iso15693_3ListenerStateReady,
|
Iso15693_3ListenerStateReady,
|
||||||
Iso15693_3ListenerStateSelected,
|
Iso15693_3ListenerStateSelected,
|
||||||
|
|||||||
Reference in New Issue
Block a user