#include "nfc_rpc_i.h"
#include "assets/compiled/mf_ultralight.pb.h"
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync_api.h>
#define TAG "NfcRpcMfUltralight"
static PB_MfUltralight_Error nfc_rpc_mf_ultralight_process_error(MfUltralightError error) {
PB_MfUltralight_Error ret = PB_MfUltralight_Error_None;
switch(error) {
case MfUltralightErrorNone:
ret = PB_MfUltralight_Error_None;
break;
case MfUltralightErrorNotPresent:
ret = PB_MfUltralight_Error_NotPresent;
break;
case MfUltralightErrorProtocol:
ret = PB_MfUltralight_Error_Protocol;
break;
case MfUltralightErrorAuth:
ret = PB_MfUltralight_Error_Auth;
break;
case MfUltralightErrorTimeout:
ret = PB_MfUltralight_Error_Timeout;
break;
default:
ret = PB_MfUltralight_Error_Timeout;
break;
}
return ret;
}
static void nfc_rpc_mf_ultralight_read_page(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_ReadPageResponse pb_mf_ul_read_page_resp =
PB_MfUltralight_ReadPageResponse_init_default;
MfUltralightPage page = {};
MfUltralightError error = mf_ultralight_poller_read_page(
instance->nfc, cmd->content.mf_ultralight_read_page_req.page, &page);
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_read_page_resp_tag;
pb_mf_ul_read_page_resp.error = nfc_rpc_mf_ultralight_process_error(error);
if(pb_mf_ul_read_page_resp.error == PB_MfUltralight_Error_None) {
pb_mf_ul_read_page_resp.page = cmd->content.mf_ultralight_read_page_req.page;
memcpy(pb_mf_ul_read_page_resp.data.bytes, &page, sizeof(MfUltralightPage));
pb_mf_ul_read_page_resp.data.size = sizeof(MfUltralightPage);
}
cmd->content.mf_ultralight_read_page_resp = pb_mf_ul_read_page_resp;
}
static void nfc_rpc_mf_ultralight_write_page(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_WritePageResponse pb_mf_ul_write_page_resp =
PB_MfUltralight_WritePageResponse_init_default;
MfUltralightPage data = {};
memcpy(&data, cmd->content.mf_ultralight_write_page_req.data.bytes, sizeof(MfUltralightPage));
uint16_t page = cmd->content.mf_ultralight_write_page_req.page;
MfUltralightError error = mf_ultralight_poller_write_page(instance->nfc, page, &data);
cmd->which_content = Nfc_Main_mf_ultralight_write_page_resp_tag;
cmd->command_status = Nfc_CommandStatus_OK;
pb_mf_ul_write_page_resp.error = nfc_rpc_mf_ultralight_process_error(error);
cmd->content.mf_ultralight_write_page_resp = pb_mf_ul_write_page_resp;
}
static void nfc_rpc_mf_ultralight_read_version(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_ReadVersionResponse pb_mf_ul_version =
PB_MfUltralight_ReadVersionResponse_init_default;
MfUltralightVersion data = {};
MfUltralightError error = mf_ultralight_poller_read_version(instance->nfc, &data);
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_read_version_resp_tag;
pb_mf_ul_version.error = nfc_rpc_mf_ultralight_process_error(error);
if(pb_mf_ul_version.error == PB_MfUltralight_Error_None) {
pb_mf_ul_version.header = data.header;
pb_mf_ul_version.prod_subtype = data.prod_subtype;
pb_mf_ul_version.prod_type = data.prod_type;
pb_mf_ul_version.prod_ver_major = data.prod_ver_major;
pb_mf_ul_version.prod_ver_minor = data.prod_ver_minor;
pb_mf_ul_version.protocol_type = data.protocol_type;
pb_mf_ul_version.storage_size = data.storage_size;
pb_mf_ul_version.vendor_id = data.vendor_id;
}
cmd->content.mf_ultralight_read_version_resp = pb_mf_ul_version;
}
static void nfc_rpc_mf_ultralight_read_signature(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_ReadSignatureResponse pb_mf_ul_signature =
PB_MfUltralight_ReadSignatureResponse_init_default;
MfUltralightSignature data = {};
MfUltralightError error = mf_ultralight_poller_read_signature(instance->nfc, &data);
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_read_signature_resp_tag;
pb_mf_ul_signature.error = nfc_rpc_mf_ultralight_process_error(error);
if(pb_mf_ul_signature.error == PB_MfUltralight_Error_None) {
memcpy(pb_mf_ul_signature.data.bytes, data.data, sizeof(MfUltralightSignature));
pb_mf_ul_signature.data.size = sizeof(MfUltralightSignature);
}
cmd->content.mf_ultralight_read_signature_resp = pb_mf_ul_signature;
}
static void nfc_rpc_mf_ultralight_read_counter(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_ReadCounterResponse pb_mf_ul_read_counter_resp =
PB_MfUltralight_ReadPageResponse_init_default;
MfUltralightCounter data = {};
MfUltralightError error = mf_ultralight_poller_read_counter(
instance->nfc, cmd->content.mf_ultralight_read_counter_req.counter_num, &data);
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_read_counter_resp_tag;
pb_mf_ul_read_counter_resp.error = nfc_rpc_mf_ultralight_process_error(error);
if(pb_mf_ul_read_counter_resp.error == PB_MfUltralight_Error_None) {
pb_mf_ul_read_counter_resp.counter_num =
cmd->content.mf_ultralight_read_counter_req.counter_num;
memcpy(pb_mf_ul_read_counter_resp.data.bytes, data.data, sizeof(MfUltralightCounter));
pb_mf_ul_read_counter_resp.data.size = sizeof(MfUltralightCounter);
}
cmd->content.mf_ultralight_read_counter_resp = pb_mf_ul_read_counter_resp;
}
static void nfc_rpc_mf_ultralight_read_tearing_flag(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_ReadTearingFlagResponse pb_mf_ul_read_tearing_flag_resp =
PB_MfUltralight_ReadTearingFlagResponse_init_default;
MfUltralightTearingFlag data = {};
MfUltralightError error = mf_ultralight_poller_read_tearing_flag(
instance->nfc, cmd->content.mf_ultralight_read_tearing_flag_req.flag_num, &data);
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_read_tearing_flag_resp_tag;
pb_mf_ul_read_tearing_flag_resp.error = nfc_rpc_mf_ultralight_process_error(error);
if(pb_mf_ul_read_tearing_flag_resp.error == PB_MfUltralight_Error_None) {
pb_mf_ul_read_tearing_flag_resp.flag_num =
cmd->content.mf_ultralight_read_tearing_flag_req.flag_num;
memcpy(
pb_mf_ul_read_tearing_flag_resp.data.bytes,
data.data,
sizeof(MfUltralightTearingFlag));
pb_mf_ul_read_tearing_flag_resp.data.size = sizeof(MfUltralightTearingFlag);
}
cmd->content.mf_ultralight_read_tearing_flag_resp = pb_mf_ul_read_tearing_flag_resp;
FURI_LOG_D(
TAG, "Tearing flag %ld: %02X", pb_mf_ul_read_tearing_flag_resp.flag_num, data.data[0]);
}
// TODO DELETE!
static void init_mf_ul_data(MfUltralightData* data) {
Iso14443_3aData* iso14443_3a_data = data->iso14443_3a_data;
uint8_t uid[7] = {0x44, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
uint8_t atqa[2] = {0x44, 0x00};
iso14443_3a_data->uid_len = sizeof(uid);
memcpy(iso14443_3a_data->uid, uid, sizeof(uid));
memcpy(iso14443_3a_data->atqa, atqa, sizeof(atqa));
iso14443_3a_data->sak = 0x00;
data->type = MfUltralightTypeUnknown;
data->pages_total = 16;
MfUltralightVersion version = {
.header = 1,
.protocol_type = 228,
};
data->version = version;
MfUltralightSignature sig = {.data = {0x01, 0x02, 0x03}};
data->signature = sig;
for(size_t i = 0; i < 16; i++) {
data->page[i].data[0] = i;
}
}
void nfc_rpc_mf_ultralight_emulate_start(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_EmulateStartResponse pb_mf_ultralight_emulate_start_resp =
PB_MfUltralight_EmulateStartResponse_init_default;
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_emulate_start_resp_tag;
if(instance->listener == NULL) {
MfUltralightData* mf_ul_data = mf_ultralight_alloc();
// TODO initialize data from rpc message
init_mf_ul_data(mf_ul_data);
instance->listener =
nfc_listener_alloc(instance->nfc, NfcProtocolMfUltralight, mf_ul_data);
nfc_listener_start(instance->listener, NULL, NULL);
pb_mf_ultralight_emulate_start_resp.error = PB_MfUltralight_Error_None;
} else {
// TODO add Busy error
pb_mf_ultralight_emulate_start_resp.error = PB_MfUltralight_Error_NotPresent;
}
cmd->content.mf_ultralight_emulate_start_resp = pb_mf_ultralight_emulate_start_resp;
}
void nfc_rpc_mf_ultralight_emulate_stop(Nfc_Main* cmd, void* context) {
furi_assert(cmd);
furi_assert(context);
NfcRpc* instance = context;
PB_MfUltralight_EmulateStopResponse pb_mf_ultralight_emulate_stop_resp =
PB_MfUltralight_EmulateStopResponse_init_default;
cmd->command_status = Nfc_CommandStatus_OK;
cmd->which_content = Nfc_Main_mf_ultralight_emulate_stop_resp_tag;
if(instance->listener) {
// Stop before free
nfc_listener_stop(instance->listener);
nfc_listener_free(instance->listener);
instance->listener = NULL;
pb_mf_ultralight_emulate_stop_resp.error = PB_MfUltralight_Error_None;
} else {
// TODO emulation not started error
pb_mf_ultralight_emulate_stop_resp.error = PB_MfUltralight_Error_NotPresent;
}
cmd->content.mf_ultralight_emulate_stop_resp = pb_mf_ultralight_emulate_stop_resp;
}
void nfc_rpc_mf_ultralight_alloc(void* context) {
furi_assert(context);
NfcRpc* instance = context;
nfc_rpc_add_handler(
instance, Nfc_Main_mf_ultralight_read_page_req_tag, nfc_rpc_mf_ultralight_read_page);
nfc_rpc_add_handler(
instance, Nfc_Main_mf_ultralight_read_version_req_tag, nfc_rpc_mf_ultralight_read_version);
nfc_rpc_add_handler(
instance, Nfc_Main_mf_ultralight_write_page_req_tag, nfc_rpc_mf_ultralight_write_page);
nfc_rpc_add_handler(
instance,
Nfc_Main_mf_ultralight_read_signature_req_tag,
nfc_rpc_mf_ultralight_read_signature);
nfc_rpc_add_handler(
instance, Nfc_Main_mf_ultralight_read_counter_req_tag, nfc_rpc_mf_ultralight_read_counter);
nfc_rpc_add_handler(
instance,
Nfc_Main_mf_ultralight_read_tearing_flag_req_tag,
nfc_rpc_mf_ultralight_read_tearing_flag);
nfc_rpc_add_handler(
instance,
Nfc_Main_mf_ultralight_emulate_start_req_tag,
nfc_rpc_mf_ultralight_emulate_start);
nfc_rpc_add_handler(
instance, Nfc_Main_mf_ultralight_emulate_stop_req_tag, nfc_rpc_mf_ultralight_emulate_stop);
}
↑ V512 A call of the 'memcpy' function will lead to overflow of the buffer 'pb_mf_ul_read_counter_resp.data.bytes'.
↑ V512 A call of the 'memcpy' function will lead to the 'data.data' buffer becoming out of range.
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'furi_log_print_format' function. The SIGNED argument of memsize type is expected.