mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-03 18:23:33 -07:00
nfc lib
This commit is contained in:
@@ -17,6 +17,13 @@ extern "C" {
|
||||
#define MF_DESFIRE_CMD_GET_FILE_IDS (0x6F)
|
||||
#define MF_DESFIRE_CMD_GET_FILE_SETTINGS (0xF5)
|
||||
|
||||
#define MF_DESFIRE_CMD_CREATE_APPLICATION (0xCA)
|
||||
#define MF_DESFIRE_CMD_CREATE_STD_DATA_FILE (0xCD)
|
||||
#define MF_DESFIRE_CMD_CREATE_BACKUP_DATA_FILE (0xCB)
|
||||
#define MF_DESFIRE_CMD_CREATE_VALUE_FILE (0xCC)
|
||||
#define MF_DESFIRE_CMD_CREATE_LINEAR_RECORD_FILE (0xC1)
|
||||
#define MF_DESFIRE_CMD_CREATE_CYCLIC_RECORD_FILE (0xC0)
|
||||
|
||||
#define MF_DESFIRE_CMD_READ_DATA (0xBD)
|
||||
#define MF_DESFIRE_CMD_GET_VALUE (0x6C)
|
||||
#define MF_DESFIRE_CMD_READ_RECORDS (0xBB)
|
||||
|
||||
@@ -60,7 +60,7 @@ bool mf_desfire_version_parse(MfDesfireVersion* data, const BitBuffer* buf) {
|
||||
bit_buffer_write_bytes(buf, data, sizeof(MfDesfireVersion));
|
||||
}
|
||||
|
||||
return can_parse;
|
||||
return can_parse && (data->hw_type & 0x0F) == 0x01;
|
||||
}
|
||||
|
||||
bool mf_desfire_free_memory_parse(MfDesfireFreeMemory* data, const BitBuffer* buf) {
|
||||
@@ -81,17 +81,17 @@ bool mf_desfire_free_memory_parse(MfDesfireFreeMemory* data, const BitBuffer* bu
|
||||
return can_parse;
|
||||
}
|
||||
|
||||
bool mf_desfire_key_settings_parse(MfDesfireKeySettings* data, const BitBuffer* buf) {
|
||||
typedef struct FURI_PACKED {
|
||||
bool is_master_key_changeable : 1;
|
||||
bool is_free_directory_list : 1;
|
||||
bool is_free_create_delete : 1;
|
||||
bool is_config_changeable : 1;
|
||||
uint8_t change_key_id : 4;
|
||||
uint8_t max_keys : 4;
|
||||
uint8_t flags : 4;
|
||||
} MfDesfireKeySettingsLayout;
|
||||
typedef struct FURI_PACKED {
|
||||
bool is_master_key_changeable : 1;
|
||||
bool is_free_directory_list : 1;
|
||||
bool is_free_create_delete : 1;
|
||||
bool is_config_changeable : 1;
|
||||
uint8_t change_key_id : 4;
|
||||
uint8_t max_keys : 4;
|
||||
uint8_t flags : 4;
|
||||
} MfDesfireKeySettingsLayout;
|
||||
|
||||
bool mf_desfire_key_settings_parse(MfDesfireKeySettings* data, const BitBuffer* buf) {
|
||||
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfDesfireKeySettingsLayout);
|
||||
|
||||
if(can_parse) {
|
||||
@@ -111,6 +111,21 @@ bool mf_desfire_key_settings_parse(MfDesfireKeySettings* data, const BitBuffer*
|
||||
return can_parse;
|
||||
}
|
||||
|
||||
void mf_desfire_key_settings_dump(const MfDesfireKeySettings* data, BitBuffer* buf) {
|
||||
MfDesfireKeySettingsLayout layout;
|
||||
|
||||
layout.is_master_key_changeable = data->is_master_key_changeable;
|
||||
layout.is_free_directory_list = data->is_free_directory_list;
|
||||
layout.is_free_create_delete = data->is_free_create_delete;
|
||||
layout.is_config_changeable = data->is_config_changeable;
|
||||
|
||||
layout.change_key_id = data->change_key_id;
|
||||
layout.max_keys = data->max_keys;
|
||||
layout.flags = data->flags;
|
||||
|
||||
bit_buffer_append_bytes(buf, (uint8_t*)&layout, sizeof(MfDesfireKeySettingsLayout));
|
||||
}
|
||||
|
||||
bool mf_desfire_key_version_parse(MfDesfireKeyVersion* data, const BitBuffer* buf) {
|
||||
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfDesfireKeyVersion);
|
||||
|
||||
|
||||
@@ -2,55 +2,11 @@
|
||||
|
||||
#include "mf_desfire.h"
|
||||
|
||||
#include <nfc/helpers/nxp_native_command.h>
|
||||
|
||||
#define MF_DESFIRE_FFF_PICC_PREFIX "PICC"
|
||||
#define MF_DESFIRE_FFF_APP_PREFIX "Application"
|
||||
|
||||
// Successful operation
|
||||
#define MF_DESFIRE_STATUS_OPERATION_OK (0x00)
|
||||
// No changes done to backup files, CommitTransaction / AbortTransaction not necessary
|
||||
#define MF_DESFIRE_STATUS_NO_CHANGES (0x0C)
|
||||
// Insufficient NV-Memory to complete command
|
||||
#define MF_DESFIRE_STATUS_OUT_OF_EEPROM_ERROR (0x0E)
|
||||
// Command code not supported
|
||||
#define MF_DESFIRE_STATUS_ILLEGAL_COMMAND_CODE (0x1C)
|
||||
// CRC or MAC does not match data Padding bytes not valid
|
||||
#define MF_DESFIRE_STATUS_INTEGRITY_ERROR (0x1E)
|
||||
// Invalid key number specified
|
||||
#define MF_DESFIRE_STATUS_NO_SUCH_KEY (0x40)
|
||||
// Length of command string invalid
|
||||
#define MF_DESFIRE_STATUS_LENGTH_ERROR (0x7E)
|
||||
// Current configuration / status does not allow the requested command
|
||||
#define MF_DESFIRE_STATUS_PERMISSION_DENIED (0x9D)
|
||||
// Value of the parameter(s) invalid
|
||||
#define MF_DESFIRE_STATUS_PARAMETER_ERROR (0x9E)
|
||||
// Requested AID not present on PICC
|
||||
#define MF_DESFIRE_STATUS_APPLICATION_NOT_FOUND (0xA0)
|
||||
// Unrecoverable error within application, application will be disabled
|
||||
#define MF_DESFIRE_STATUS_APPL_INTEGRITY_ERROR (0xA1)
|
||||
// Current authentication status does not allow the requested command
|
||||
#define MF_DESFIRE_STATUS_AUTHENTICATION_ERROR (0xAE)
|
||||
// Additional data frame is expected to be sent
|
||||
#define MF_DESFIRE_STATUS_ADDITIONAL_FRAME (0xAF)
|
||||
// Attempt to read/write data from/to beyond the file's/record's limits
|
||||
// Attempt to exceed the limits of a value file.
|
||||
#define MF_DESFIRE_STATUS_BOUNDARY_ERROR (0xBE)
|
||||
// Unrecoverable error within PICC, PICC will be disabled
|
||||
#define MF_DESFIRE_STATUS_PICC_INTEGRITY_ERROR (0xC1)
|
||||
// Previous Command was not fully completed. Not all Frames were requested or provided by the PCD
|
||||
#define MF_DESFIRE_STATUS_COMMAND_ABORTED (0xCA)
|
||||
// PICC was disabled by an unrecoverable error
|
||||
#define MF_DESFIRE_STATUS_PICC_DISABLED_ERROR (0xCD)
|
||||
// Number of Applications limited to 28, no additional CreateApplication possible
|
||||
#define MF_DESFIRE_STATUS_COUNT_ERROR (0xCE)
|
||||
// Creation of file/application failed because file/application with same number already exists
|
||||
#define MF_DESFIRE_STATUS_DUBLICATE_ERROR (0xDE)
|
||||
// Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated
|
||||
#define MF_DESFIRE_STATUS_EEPROM_ERROR (0xEE)
|
||||
// Specified file number does not exist
|
||||
#define MF_DESFIRE_STATUS_FILE_NOT_FOUND (0xF0)
|
||||
// Unrecoverable error within file, file will be disabled
|
||||
#define MF_DESFIRE_STATUS_FILE_INTEGRITY_ERROR (0xF1)
|
||||
|
||||
// SimpleArray configurations
|
||||
|
||||
extern const SimpleArrayConfig mf_desfire_key_version_array_config;
|
||||
@@ -68,6 +24,8 @@ bool mf_desfire_free_memory_parse(MfDesfireFreeMemory* data, const BitBuffer* bu
|
||||
|
||||
bool mf_desfire_key_settings_parse(MfDesfireKeySettings* data, const BitBuffer* buf);
|
||||
|
||||
void mf_desfire_key_settings_dump(const MfDesfireKeySettings* data, BitBuffer* buf);
|
||||
|
||||
bool mf_desfire_key_version_parse(MfDesfireKeyVersion* data, const BitBuffer* buf);
|
||||
|
||||
bool mf_desfire_application_id_parse(
|
||||
|
||||
@@ -251,8 +251,7 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
|
||||
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
MfDesfireVersion version = {};
|
||||
error = mf_desfire_poller_read_version(instance, &version);
|
||||
error = mf_desfire_poller_read_version(instance, &instance->data->version);
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
protocol_detected = true;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "mf_desfire.h"
|
||||
|
||||
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
|
||||
#include <lib/nfc/helpers/nxp_native_command_mode.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -38,6 +39,16 @@ typedef struct {
|
||||
MfDesfirePollerEventData* data; /**< Pointer to event specific data. */
|
||||
} MfDesfirePollerEvent;
|
||||
|
||||
/**
|
||||
* @brief Change command mode used in poller mode.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to affect.
|
||||
* @param[in] command_mode command mode to use in further communication with the card.
|
||||
*/
|
||||
void mf_desfire_poller_set_command_mode(
|
||||
MfDesfirePoller* instance,
|
||||
NxpNativeCommandMode command_mode);
|
||||
|
||||
/**
|
||||
* @brief Transmit and receive MfDesfire chunks in poller mode.
|
||||
*
|
||||
@@ -51,11 +62,16 @@ typedef struct {
|
||||
* @param[out] rx_buffer pointer to the buffer to be filled with received data.
|
||||
* @return MfDesfireErrorNone on success, an error code on failure.
|
||||
*/
|
||||
MfDesfireError mf_desfire_send_chunks(
|
||||
MfDesfireError mf_desfire_poller_send_chunks(
|
||||
MfDesfirePoller* instance,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer);
|
||||
|
||||
/**
|
||||
* @warning deprecated, use mf_desfire_poller_send_chunks instead
|
||||
*/
|
||||
#define mf_desfire_send_chunks mf_desfire_poller_send_chunks
|
||||
|
||||
/**
|
||||
* @brief Read MfDesfire card version.
|
||||
*
|
||||
@@ -187,6 +203,44 @@ MfDesfireError mf_desfire_poller_read_file_settings_multi(
|
||||
const SimpleArray* file_ids,
|
||||
SimpleArray* data);
|
||||
|
||||
/**
|
||||
* @brief Create Application on MfDesfire card.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] id pointer to the application id for the new application.
|
||||
* @param[in] key_settings pointer to the key settings for the new application.
|
||||
* @param[in] iso_df_id optional iso identifier for the new application.
|
||||
* @param[in] iso_df_name optional iso name for the new application.
|
||||
* @param[in] iso_df_name_len length of the optional iso application name.
|
||||
* @return MfDesfireErrorNone on success, an error code on failure.
|
||||
*/
|
||||
MfDesfireError mf_desfire_poller_create_application(
|
||||
MfDesfirePoller* instance,
|
||||
const MfDesfireApplicationId* id,
|
||||
const MfDesfireKeySettings* key_settings,
|
||||
uint16_t iso_df_id,
|
||||
const uint8_t* iso_df_name,
|
||||
uint8_t iso_df_name_len);
|
||||
|
||||
/**
|
||||
* @brief Create File on MfDesfire card.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] id file id for the new file.
|
||||
* @param[in] data pointer to the file settings for the new file.
|
||||
* @param[in] iso_ef_id optional iso identifier for the new file.
|
||||
* @return MfDesfireErrorNone on success, an error code on failure.
|
||||
*/
|
||||
MfDesfireError mf_desfire_poller_create_file(
|
||||
MfDesfirePoller* instance,
|
||||
MfDesfireFileId id,
|
||||
const MfDesfireFileSettings* data,
|
||||
uint16_t iso_ef_id);
|
||||
|
||||
/**
|
||||
* @brief Read file data on MfDesfire card.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "mf_desfire_poller_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
#include "mf_desfire_i.h"
|
||||
|
||||
@@ -21,76 +22,48 @@ MfDesfireError mf_desfire_process_error(Iso14443_4aError error) {
|
||||
|
||||
MfDesfireError mf_desfire_process_status_code(uint8_t status_code) {
|
||||
switch(status_code) {
|
||||
case MF_DESFIRE_STATUS_OPERATION_OK:
|
||||
case NXP_NATIVE_COMMAND_STATUS_OPERATION_OK:
|
||||
return MfDesfireErrorNone;
|
||||
case MF_DESFIRE_STATUS_AUTHENTICATION_ERROR:
|
||||
case NXP_NATIVE_COMMAND_STATUS_AUTHENTICATION_ERROR:
|
||||
return MfDesfireErrorAuthentication;
|
||||
case MF_DESFIRE_STATUS_ILLEGAL_COMMAND_CODE:
|
||||
case NXP_NATIVE_COMMAND_STATUS_ILLEGAL_COMMAND_CODE:
|
||||
return MfDesfireErrorCommandNotSupported;
|
||||
default:
|
||||
return MfDesfireErrorProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
MfDesfireError mf_desfire_send_chunks(
|
||||
void mf_desfire_poller_set_command_mode(
|
||||
MfDesfirePoller* instance,
|
||||
NxpNativeCommandMode command_mode) {
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == MfDesfirePollerStateIdle);
|
||||
furi_check(command_mode < NxpNativeCommandModeMAX);
|
||||
|
||||
instance->command_mode = command_mode;
|
||||
}
|
||||
|
||||
MfDesfireError mf_desfire_poller_send_chunks(
|
||||
MfDesfirePoller* instance,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer) {
|
||||
furi_check(instance);
|
||||
furi_check(instance->iso14443_4a_poller);
|
||||
furi_check(instance->tx_buffer);
|
||||
furi_check(instance->rx_buffer);
|
||||
furi_check(tx_buffer);
|
||||
furi_check(rx_buffer);
|
||||
|
||||
MfDesfireError error = MfDesfireErrorNone;
|
||||
NxpNativeCommandStatus status_code = NXP_NATIVE_COMMAND_STATUS_OPERATION_OK;
|
||||
Iso14443_4aError iso14443_4a_error = nxp_native_command_iso14443_4a_poller(
|
||||
instance->iso14443_4a_poller,
|
||||
&status_code,
|
||||
tx_buffer,
|
||||
rx_buffer,
|
||||
instance->command_mode,
|
||||
instance->tx_buffer,
|
||||
instance->rx_buffer);
|
||||
|
||||
do {
|
||||
Iso14443_4aError iso14443_4a_error = iso14443_4a_poller_send_block(
|
||||
instance->iso14443_4a_poller, tx_buffer, instance->rx_buffer);
|
||||
|
||||
if(iso14443_4a_error != Iso14443_4aErrorNone) {
|
||||
error = mf_desfire_process_error(iso14443_4a_error);
|
||||
break;
|
||||
}
|
||||
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_STATUS_ADDITIONAL_FRAME);
|
||||
|
||||
if(bit_buffer_get_size_bytes(instance->rx_buffer) > sizeof(uint8_t)) {
|
||||
bit_buffer_copy_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t));
|
||||
} else {
|
||||
bit_buffer_reset(rx_buffer);
|
||||
}
|
||||
|
||||
while(
|
||||
bit_buffer_starts_with_byte(instance->rx_buffer, MF_DESFIRE_STATUS_ADDITIONAL_FRAME)) {
|
||||
Iso14443_4aError iso14443_4a_error = iso14443_4a_poller_send_block(
|
||||
instance->iso14443_4a_poller, instance->tx_buffer, instance->rx_buffer);
|
||||
|
||||
if(iso14443_4a_error != Iso14443_4aErrorNone) {
|
||||
error = mf_desfire_process_error(iso14443_4a_error);
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t rx_size = bit_buffer_get_size_bytes(instance->rx_buffer);
|
||||
const size_t rx_capacity_remaining =
|
||||
bit_buffer_get_capacity_bytes(rx_buffer) - bit_buffer_get_size_bytes(rx_buffer);
|
||||
|
||||
if(rx_size <= rx_capacity_remaining + 1) {
|
||||
bit_buffer_append_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t));
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 1);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(error == MfDesfireErrorNone) {
|
||||
uint8_t err_code = bit_buffer_get_byte(instance->rx_buffer, 0);
|
||||
error = mf_desfire_process_status_code(err_code);
|
||||
if(iso14443_4a_error != Iso14443_4aErrorNone) {
|
||||
return mf_desfire_process_error(iso14443_4a_error);
|
||||
}
|
||||
|
||||
return error;
|
||||
return mf_desfire_process_status_code(status_code);
|
||||
}
|
||||
|
||||
MfDesfireError mf_desfire_poller_read_version(MfDesfirePoller* instance, MfDesfireVersion* data) {
|
||||
@@ -102,7 +75,8 @@ MfDesfireError mf_desfire_poller_read_version(MfDesfirePoller* instance, MfDesfi
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -124,7 +98,8 @@ MfDesfireError
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -146,7 +121,8 @@ MfDesfireError
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -170,7 +146,7 @@ MfDesfireError mf_desfire_poller_read_key_version(
|
||||
bit_buffer_set_byte(instance->input_buffer, 1, key_num);
|
||||
|
||||
MfDesfireError error =
|
||||
mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
mf_desfire_poller_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
if(error == MfDesfireErrorNone) {
|
||||
if(!mf_desfire_key_version_parse(data, instance->result_buffer)) {
|
||||
error = MfDesfireErrorProtocol;
|
||||
@@ -210,7 +186,8 @@ MfDesfireError
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -243,7 +220,7 @@ MfDesfireError mf_desfire_poller_select_application(
|
||||
instance->input_buffer, (const uint8_t*)id, sizeof(MfDesfireApplicationId));
|
||||
|
||||
MfDesfireError error =
|
||||
mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
mf_desfire_poller_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -258,7 +235,8 @@ MfDesfireError mf_desfire_poller_read_file_ids(MfDesfirePoller* instance, Simple
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -293,7 +271,8 @@ MfDesfireError mf_desfire_poller_read_file_settings(
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
@@ -329,6 +308,108 @@ MfDesfireError mf_desfire_poller_read_file_settings_multi(
|
||||
return error;
|
||||
}
|
||||
|
||||
MfDesfireError mf_desfire_poller_create_application(
|
||||
MfDesfirePoller* instance,
|
||||
const MfDesfireApplicationId* id,
|
||||
const MfDesfireKeySettings* key_settings,
|
||||
uint16_t iso_df_id,
|
||||
const uint8_t* iso_df_name,
|
||||
uint8_t iso_df_name_len) {
|
||||
furi_check(instance);
|
||||
furi_check(key_settings);
|
||||
|
||||
bit_buffer_reset(instance->input_buffer);
|
||||
bit_buffer_append_byte(instance->input_buffer, MF_DESFIRE_CMD_CREATE_APPLICATION);
|
||||
bit_buffer_append_bytes(
|
||||
instance->input_buffer, (const uint8_t*)id, sizeof(MfDesfireApplicationId));
|
||||
mf_desfire_key_settings_dump(key_settings, instance->input_buffer);
|
||||
|
||||
if(iso_df_name && iso_df_name_len) {
|
||||
uint8_t ks2_pos = bit_buffer_get_size_bytes(instance->input_buffer) - 1;
|
||||
uint8_t ks2 = bit_buffer_get_byte(instance->input_buffer, ks2_pos);
|
||||
ks2 |= (1 << 5); // Mark file id present
|
||||
bit_buffer_set_byte(instance->input_buffer, ks2_pos, ks2);
|
||||
|
||||
uint8_t iso_df_id_le[sizeof(iso_df_id)];
|
||||
bit_lib_num_to_bytes_le(iso_df_id, sizeof(iso_df_id_le), iso_df_id_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, iso_df_id_le, sizeof(iso_df_id_le));
|
||||
|
||||
bit_buffer_append_bytes(instance->input_buffer, iso_df_name, iso_df_name_len);
|
||||
}
|
||||
|
||||
MfDesfireError error =
|
||||
mf_desfire_poller_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
MfDesfireError mf_desfire_poller_create_file(
|
||||
MfDesfirePoller* instance,
|
||||
MfDesfireFileId id,
|
||||
const MfDesfireFileSettings* data,
|
||||
uint16_t iso_ef_id) {
|
||||
furi_check(instance);
|
||||
furi_check(data);
|
||||
|
||||
bit_buffer_reset(instance->input_buffer);
|
||||
bit_buffer_append_byte(
|
||||
instance->input_buffer,
|
||||
data->type == MfDesfireFileTypeStandard ? MF_DESFIRE_CMD_CREATE_STD_DATA_FILE :
|
||||
data->type == MfDesfireFileTypeBackup ? MF_DESFIRE_CMD_CREATE_BACKUP_DATA_FILE :
|
||||
data->type == MfDesfireFileTypeValue ? MF_DESFIRE_CMD_CREATE_VALUE_FILE :
|
||||
data->type == MfDesfireFileTypeLinearRecord ? MF_DESFIRE_CMD_CREATE_LINEAR_RECORD_FILE :
|
||||
data->type == MfDesfireFileTypeCyclicRecord ? MF_DESFIRE_CMD_CREATE_CYCLIC_RECORD_FILE :
|
||||
0x00);
|
||||
bit_buffer_append_byte(instance->input_buffer, id);
|
||||
if(iso_ef_id) {
|
||||
uint8_t iso_ef_id_le[sizeof(iso_ef_id)];
|
||||
bit_lib_num_to_bytes_le(iso_ef_id, sizeof(iso_ef_id_le), iso_ef_id_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, iso_ef_id_le, sizeof(iso_ef_id_le));
|
||||
}
|
||||
bit_buffer_append_byte(instance->input_buffer, data->comm);
|
||||
bit_buffer_append_bytes(
|
||||
instance->input_buffer,
|
||||
(const uint8_t*)data->access_rights,
|
||||
sizeof(MfDesfireFileAccessRights) * data->access_rights_len);
|
||||
|
||||
if(data->type == MfDesfireFileTypeStandard || data->type == MfDesfireFileTypeBackup) {
|
||||
uint8_t data_size_le[3 * sizeof(uint8_t)];
|
||||
bit_lib_num_to_bytes_le(data->data.size, sizeof(data_size_le), data_size_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, data_size_le, sizeof(data_size_le));
|
||||
|
||||
} else if(data->type == MfDesfireFileTypeValue) {
|
||||
uint8_t lo_limit_le[sizeof(data->value.lo_limit)];
|
||||
bit_lib_num_to_bytes_le(data->value.lo_limit, sizeof(lo_limit_le), lo_limit_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, lo_limit_le, sizeof(lo_limit_le));
|
||||
|
||||
uint8_t hi_limit_le[sizeof(data->value.hi_limit)];
|
||||
bit_lib_num_to_bytes_le(data->value.hi_limit, sizeof(hi_limit_le), hi_limit_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, hi_limit_le, sizeof(hi_limit_le));
|
||||
|
||||
uint8_t value_le[sizeof(data->value.limited_credit_value)];
|
||||
bit_lib_num_to_bytes_le(data->value.limited_credit_value, sizeof(value_le), value_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, value_le, sizeof(value_le));
|
||||
|
||||
bit_buffer_append_byte(instance->input_buffer, data->value.limited_credit_enabled);
|
||||
|
||||
} else if(
|
||||
data->type == MfDesfireFileTypeLinearRecord ||
|
||||
data->type == MfDesfireFileTypeCyclicRecord) {
|
||||
uint8_t record_size_le[3 * sizeof(uint8_t)];
|
||||
bit_lib_num_to_bytes_le(data->record.size, sizeof(record_size_le), record_size_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, record_size_le, sizeof(record_size_le));
|
||||
|
||||
uint8_t record_max_le[3 * sizeof(uint8_t)];
|
||||
bit_lib_num_to_bytes_le(data->record.max, sizeof(record_max_le), record_max_le);
|
||||
bit_buffer_append_bytes(instance->input_buffer, record_max_le, sizeof(record_max_le));
|
||||
}
|
||||
|
||||
MfDesfireError error =
|
||||
mf_desfire_poller_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static MfDesfireError mf_desfire_poller_read_file(
|
||||
MfDesfirePoller* instance,
|
||||
MfDesfireFileId id,
|
||||
@@ -354,7 +435,8 @@ static MfDesfireError mf_desfire_poller_read_file(
|
||||
bit_buffer_append_bytes(instance->input_buffer, (const uint8_t*)¤t_offset, 3);
|
||||
bit_buffer_append_bytes(instance->input_buffer, (const uint8_t*)&bytes_to_read, 3);
|
||||
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
size_t bytes_received = bit_buffer_get_size_bytes(instance->result_buffer);
|
||||
@@ -400,7 +482,8 @@ MfDesfireError mf_desfire_poller_read_file_value(
|
||||
MfDesfireError error;
|
||||
|
||||
do {
|
||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||
error = mf_desfire_poller_send_chunks(
|
||||
instance, instance->input_buffer, instance->result_buffer);
|
||||
|
||||
if(error != MfDesfireErrorNone) break;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef enum {
|
||||
|
||||
struct MfDesfirePoller {
|
||||
Iso14443_4aPoller* iso14443_4a_poller;
|
||||
NxpNativeCommandMode command_mode;
|
||||
MfDesfirePollerSessionState session_state;
|
||||
MfDesfirePollerState state;
|
||||
MfDesfireError error;
|
||||
|
||||
Reference in New Issue
Block a user