diff --git a/lib/nfc/helpers/nxp_native_command.c b/lib/nfc/helpers/nxp_native_command.c new file mode 100644 index 000000000..d5d535891 --- /dev/null +++ b/lib/nfc/helpers/nxp_native_command.c @@ -0,0 +1,115 @@ +#include "nxp_native_command.h" + +#include + +#define TAG "NxpNativeCommand" + +Iso14443_4aError nxp_native_command_iso14443_4a_poller( + Iso14443_4aPoller* iso14443_4a_poller, + NxpNativeCommandStatus* status_code, + const BitBuffer* input_buffer, + BitBuffer* result_buffer, + NxpNativeCommandMode command_mode, + BitBuffer* tx_buffer, + BitBuffer* rx_buffer) { + furi_check(iso14443_4a_poller); + furi_check(tx_buffer); + furi_check(rx_buffer); + furi_check(input_buffer); + furi_check(result_buffer); + furi_check(command_mode < NxpNativeCommandModeMAX); + + Iso14443_4aError error = Iso14443_4aErrorNone; + *status_code = NXP_NATIVE_COMMAND_STATUS_OPERATION_OK; + + do { + bit_buffer_reset(tx_buffer); + if(command_mode == NxpNativeCommandModePlain) { + bit_buffer_append(tx_buffer, input_buffer); + } else if(command_mode == NxpNativeCommandModeIsoWrapped) { + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_CLA); + bit_buffer_append_byte(tx_buffer, bit_buffer_get_byte(input_buffer, 0)); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P1); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P2); + if(bit_buffer_get_size_bytes(input_buffer) > 1) { + bit_buffer_append_byte(tx_buffer, bit_buffer_get_size_bytes(input_buffer) - 1); + bit_buffer_append_right(tx_buffer, input_buffer, 1); + } + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_LE); + } + + bit_buffer_reset(rx_buffer); + error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer); + + if(error != Iso14443_4aErrorNone) { + break; + } + + bit_buffer_reset(tx_buffer); + if(command_mode == NxpNativeCommandModePlain) { + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME); + } else if(command_mode == NxpNativeCommandModeIsoWrapped) { + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_CLA); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P1); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P2); + bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_LE); + } + + size_t response_len = bit_buffer_get_size_bytes(rx_buffer); + *status_code = NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR; + bit_buffer_reset(result_buffer); + if(command_mode == NxpNativeCommandModePlain && response_len >= sizeof(uint8_t)) { + *status_code = bit_buffer_get_byte(rx_buffer, 0); + if(response_len > sizeof(uint8_t)) { + bit_buffer_copy_right(result_buffer, rx_buffer, sizeof(uint8_t)); + } + } else if( + command_mode == NxpNativeCommandModeIsoWrapped && + response_len >= 2 * sizeof(uint8_t) && + bit_buffer_get_byte(rx_buffer, response_len - 2) == NXP_NATIVE_COMMAND_ISO_SW1) { + *status_code = bit_buffer_get_byte(rx_buffer, response_len - 1); + if(response_len > 2 * sizeof(uint8_t)) { + bit_buffer_copy_left(result_buffer, rx_buffer, response_len - 2 * sizeof(uint8_t)); + } + } + + while(*status_code == NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME) { + bit_buffer_reset(rx_buffer); + error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer); + + if(error != Iso14443_4aErrorNone) { + break; + } + + const size_t rx_size = bit_buffer_get_size_bytes(rx_buffer); + const size_t rx_capacity_remaining = bit_buffer_get_capacity_bytes(result_buffer) - + bit_buffer_get_size_bytes(result_buffer); + + if(command_mode == NxpNativeCommandModePlain) { + *status_code = rx_size >= 1 ? bit_buffer_get_byte(rx_buffer, 0) : + NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR; + if(rx_size <= rx_capacity_remaining + 1) { + bit_buffer_append_right(result_buffer, rx_buffer, sizeof(uint8_t)); + } else { + FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 1); + } + } else if(command_mode == NxpNativeCommandModeIsoWrapped) { + if(rx_size >= 2 && + bit_buffer_get_byte(rx_buffer, rx_size - 2) == NXP_NATIVE_COMMAND_ISO_SW1) { + *status_code = bit_buffer_get_byte(rx_buffer, rx_size - 1); + } else { + *status_code = NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR; + } + if(rx_size <= rx_capacity_remaining + 2) { + bit_buffer_set_size_bytes(rx_buffer, rx_size - 2); + bit_buffer_append(result_buffer, rx_buffer); + } else { + FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 2); + } + } + } + } while(false); + + return error; +} diff --git a/lib/nfc/helpers/nxp_native_command.h b/lib/nfc/helpers/nxp_native_command.h new file mode 100644 index 000000000..61677a3f6 --- /dev/null +++ b/lib/nfc/helpers/nxp_native_command.h @@ -0,0 +1,92 @@ +#pragma once + +#include "nxp_native_command_mode.h" + +#include + +// ISO 7816 command wrapping +#define NXP_NATIVE_COMMAND_ISO_CLA (0x90) +#define NXP_NATIVE_COMMAND_ISO_P1 (0x00) +#define NXP_NATIVE_COMMAND_ISO_P2 (0x00) +#define NXP_NATIVE_COMMAND_ISO_LE (0x00) +// ISO 7816 status wrapping +#define NXP_NATIVE_COMMAND_ISO_SW1 (0x91) + +// Successful operation +#define NXP_NATIVE_COMMAND_STATUS_OPERATION_OK (0x00) +// No changes done to backup files, CommitTransaction / AbortTransaction not necessary +#define NXP_NATIVE_COMMAND_STATUS_NO_CHANGES (0x0C) +// Insufficient NV-Memory to complete command +#define NXP_NATIVE_COMMAND_STATUS_OUT_OF_EEPROM_ERROR (0x0E) +// Command code not supported +#define NXP_NATIVE_COMMAND_STATUS_ILLEGAL_COMMAND_CODE (0x1C) +// CRC or MAC does not match data Padding bytes not valid +#define NXP_NATIVE_COMMAND_STATUS_INTEGRITY_ERROR (0x1E) +// Invalid key number specified +#define NXP_NATIVE_COMMAND_STATUS_NO_SUCH_KEY (0x40) +// Length of command string invalid +#define NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR (0x7E) +// Current configuration / status does not allow the requested command +#define NXP_NATIVE_COMMAND_STATUS_PERMISSION_DENIED (0x9D) +// Value of the parameter(s) invalid +#define NXP_NATIVE_COMMAND_STATUS_PARAMETER_ERROR (0x9E) +// Requested AID not present on PICC +#define NXP_NATIVE_COMMAND_STATUS_APPLICATION_NOT_FOUND (0xA0) +// Unrecoverable error within application, application will be disabled +#define NXP_NATIVE_COMMAND_STATUS_APPL_INTEGRITY_ERROR (0xA1) +// Currently not allowed to authenticate. Keep trying until full delay is spent +#define NXP_NATIVE_COMMAND_STATUS_STATUS_AUTHENTICATION_DELAY (0xAD) +// Current authentication status does not allow the requested command +#define NXP_NATIVE_COMMAND_STATUS_AUTHENTICATION_ERROR (0xAE) +// Additional data frame is expected to be sent +#define NXP_NATIVE_COMMAND_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 NXP_NATIVE_COMMAND_STATUS_BOUNDARY_ERROR (0xBE) +// Unrecoverable error within PICC, PICC will be disabled +#define NXP_NATIVE_COMMAND_STATUS_PICC_INTEGRITY_ERROR (0xC1) +// Previous Command was not fully completed. Not all Frames were requested or provided by the PCD +#define NXP_NATIVE_COMMAND_STATUS_COMMAND_ABORTED (0xCA) +// PICC was disabled by an unrecoverable error +#define NXP_NATIVE_COMMAND_STATUS_PICC_DISABLED_ERROR (0xCD) +// Number of Applications limited to 28, no additional CreateApplication possible +#define NXP_NATIVE_COMMAND_STATUS_COUNT_ERROR (0xCE) +// Creation of file/application failed because file/application with same number already exists +#define NXP_NATIVE_COMMAND_STATUS_DUBLICATE_ERROR (0xDE) +// Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated +#define NXP_NATIVE_COMMAND_STATUS_EEPROM_ERROR (0xEE) +// Specified file number does not exist +#define NXP_NATIVE_COMMAND_STATUS_FILE_NOT_FOUND (0xF0) +// Unrecoverable error within file, file will be disabled +#define NXP_NATIVE_COMMAND_STATUS_FILE_INTEGRITY_ERROR (0xF1) + +typedef uint8_t NxpNativeCommandStatus; + +/** + * @brief Transmit and receive NXP Native Command chunks in poller mode. + * + * Must ONLY be used inside the callback function. + * + * The result_buffer will be filled with any data received as a response to data + * sent from input_buffer, with a timeout defined by the fwt parameter. + * + * The tx_buffer and rx_buffer are used as working areas to handle individual + * command chunks and responses. + * + * @param[in, out] iso14443_4a_poller pointer to the instance to be used in the transaction. + * @param[out] status_code pointer to a status variable to hold the result of the operation. + * @param[in] input_buffer pointer to the buffer containing the data to be transmitted. + * @param[out] result_buffer pointer to the buffer to be filled with received data. + * @param[in] command_mode what command formatting mode to use for the transaction. + * @param[in, out] tx_buffer pointer to the buffer for command construction. + * @param[in, out] rx_buffer pointer to the buffer for response handling. + * @return Iso14443_4aErrorNone and STATUS_OPERATION_OK on success, an error code on failure. + */ +Iso14443_4aError nxp_native_command_iso14443_4a_poller( + Iso14443_4aPoller* iso14443_4a_poller, + NxpNativeCommandStatus* status_code, + const BitBuffer* input_buffer, + BitBuffer* result_buffer, + NxpNativeCommandMode command_mode, + BitBuffer* tx_buffer, + BitBuffer* rx_buffer); diff --git a/lib/nfc/helpers/nxp_native_command_mode.h b/lib/nfc/helpers/nxp_native_command_mode.h new file mode 100644 index 000000000..7684b4d48 --- /dev/null +++ b/lib/nfc/helpers/nxp_native_command_mode.h @@ -0,0 +1,11 @@ +#pragma once + +/** + * @brief Enumeration of possible command modes. + */ +typedef enum { + NxpNativeCommandModePlain, /**< Plain native commands. */ + NxpNativeCommandModeIsoWrapped, /**< ISO 7816-wrapped commands. */ + + NxpNativeCommandModeMAX, +} NxpNativeCommandMode; diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_i.h b/lib/nfc/protocols/mf_desfire/mf_desfire_i.h index 526a4e0b8..ac572ae58 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_i.h +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_i.h @@ -2,63 +2,11 @@ #include "mf_desfire.h" +#include + #define MF_DESFIRE_FFF_PICC_PREFIX "PICC" #define MF_DESFIRE_FFF_APP_PREFIX "Application" -// ISO 7816 command wrapping -#define MF_DESFIRE_CMD_ISO_CLA (0x90) -#define MF_DESFIRE_CMD_ISO_P1 (0x00) -#define MF_DESFIRE_CMD_ISO_P2 (0x00) -#define MF_DESFIRE_CMD_ISO_LE (0x00) -// ISO 7816 status wrapping -#define MF_DESFIRE_STATUS_ISO_SW1 (0x91) - -// 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; diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h index 683b12359..4010938e5 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h @@ -3,6 +3,7 @@ #include "mf_desfire.h" #include +#include #ifdef __cplusplus extern "C" { @@ -39,24 +40,14 @@ typedef struct { } MfDesfirePollerEvent; /** - * @brief Enumeration of possible MfDesfire poller command modes. - */ -typedef enum { - MfDesfirePollerCommandModeNative, /**< Native MfDesfire commands. */ - MfDesfirePollerCommandModeIsoWrapped, /**< ISO 7816-wrapped commands. */ - - MfDesfirePollerCommandModeMAX, -} MfDesfirePollerCommandMode; - -/** - * @brief Change MfDesfire command mode used in poller mode. + * @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, - MfDesfirePollerCommandMode command_mode); + NxpNativeCommandMode command_mode); /** * @brief Transmit and receive MfDesfire chunks in poller mode. diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c index 21d88623f..b8aad6e0d 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c @@ -22,11 +22,11 @@ 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; @@ -35,10 +35,10 @@ MfDesfireError mf_desfire_process_status_code(uint8_t status_code) { void mf_desfire_poller_set_command_mode( MfDesfirePoller* instance, - MfDesfirePollerCommandMode command_mode) { + NxpNativeCommandMode command_mode) { furi_check(instance); furi_check(instance->state == MfDesfirePollerStateIdle); - furi_check(command_mode < MfDesfirePollerCommandModeMAX); + furi_check(command_mode < NxpNativeCommandModeMAX); instance->command_mode = command_mode; } @@ -48,111 +48,22 @@ MfDesfireError mf_desfire_poller_send_chunks( 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; - uint8_t status_code = MF_DESFIRE_STATUS_OPERATION_OK; + 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 { - bit_buffer_reset(instance->tx_buffer); - if(instance->command_mode == MfDesfirePollerCommandModeNative) { - bit_buffer_append(instance->tx_buffer, tx_buffer); - } else if(instance->command_mode == MfDesfirePollerCommandModeIsoWrapped) { - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_CLA); - bit_buffer_append_byte(instance->tx_buffer, bit_buffer_get_byte(tx_buffer, 0)); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_P1); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_P2); - if(bit_buffer_get_size_bytes(tx_buffer) > 1) { - bit_buffer_append_byte( - instance->tx_buffer, bit_buffer_get_size_bytes(tx_buffer) - 1); - bit_buffer_append_right(instance->tx_buffer, tx_buffer, 1); - } - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_LE); - } - - 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; - } - - bit_buffer_reset(instance->tx_buffer); - if(instance->command_mode == MfDesfirePollerCommandModeNative) { - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_STATUS_ADDITIONAL_FRAME); - } else if(instance->command_mode == MfDesfirePollerCommandModeIsoWrapped) { - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_CLA); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_STATUS_ADDITIONAL_FRAME); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_P1); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_P2); - bit_buffer_append_byte(instance->tx_buffer, MF_DESFIRE_CMD_ISO_LE); - } - - size_t response_len = bit_buffer_get_size_bytes(instance->rx_buffer); - status_code = MF_DESFIRE_STATUS_LENGTH_ERROR; - bit_buffer_reset(rx_buffer); - if(instance->command_mode == MfDesfirePollerCommandModeNative && - response_len >= sizeof(uint8_t)) { - status_code = bit_buffer_get_byte(instance->rx_buffer, 0); - if(response_len > sizeof(uint8_t)) { - bit_buffer_copy_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t)); - } - } else if( - instance->command_mode == MfDesfirePollerCommandModeIsoWrapped && - response_len >= 2 * sizeof(uint8_t) && - bit_buffer_get_byte(instance->rx_buffer, response_len - 2) == - MF_DESFIRE_STATUS_ISO_SW1) { - status_code = bit_buffer_get_byte(instance->rx_buffer, response_len - 1); - if(response_len > 2 * sizeof(uint8_t)) { - bit_buffer_copy_left( - rx_buffer, instance->rx_buffer, response_len - 2 * sizeof(uint8_t)); - } - } - - while(status_code == 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(instance->command_mode == MfDesfirePollerCommandModeNative) { - status_code = rx_size < 1 ? MF_DESFIRE_STATUS_LENGTH_ERROR : - bit_buffer_get_byte(instance->rx_buffer, 0); - 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); - } - } else if(instance->command_mode == MfDesfirePollerCommandModeIsoWrapped) { - status_code = rx_size < 2 ? MF_DESFIRE_STATUS_LENGTH_ERROR : - bit_buffer_get_byte(instance->rx_buffer, rx_size - 1); - if(rx_size <= rx_capacity_remaining + 2) { - bit_buffer_set_size_bytes(instance->rx_buffer, rx_size - 2); - bit_buffer_append(rx_buffer, instance->rx_buffer); - } else { - FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 2); - } - } - } - } while(false); - - if(error == MfDesfireErrorNone) { - error = mf_desfire_process_status_code(status_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) { diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.h b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.h index 135e2ec98..179fd44b5 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.h +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.h @@ -30,7 +30,7 @@ typedef enum { struct MfDesfirePoller { Iso14443_4aPoller* iso14443_4a_poller; - MfDesfirePollerCommandMode command_mode; + NxpNativeCommandMode command_mode; MfDesfirePollerSessionState session_state; MfDesfirePollerState state; MfDesfireError error; diff --git a/lib/nfc/protocols/mf_plus/mf_plus_i.c b/lib/nfc/protocols/mf_plus/mf_plus_i.c index 8f06a644a..3d533eb58 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_i.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_i.c @@ -238,22 +238,10 @@ MfPlusError } MfPlusError mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf) { - bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusVersion); + const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusVersion); if(can_parse) { bit_buffer_write_bytes(buf, data, sizeof(MfPlusVersion)); - } else if( - bit_buffer_get_size_bytes(buf) == 8 && - bit_buffer_get_byte(buf, 0) == MF_PLUS_STATUS_ADDITIONAL_FRAME) { - // HACK(-nofl): There are supposed to be three parts to the GetVersion command, - // with the second and third parts fetched by sending the AdditionalFrame - // command. I don't know whether the entire MIFARE Plus line uses status as - // the first byte, so let's just assume we only have the first part of - // the response if it's size 8 and starts with the AF status. The second - // part of the response is the same size and status byte, but so far - // we're only reading one response. - can_parse = true; - bit_buffer_write_bytes_mid(buf, data, 1, bit_buffer_get_size_bytes(buf) - 1); } return can_parse ? MfPlusErrorNone : MfPlusErrorProtocol; diff --git a/lib/nfc/protocols/mf_plus/mf_plus_i.h b/lib/nfc/protocols/mf_plus/mf_plus_i.h index 302f5a178..cadc435b9 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_i.h +++ b/lib/nfc/protocols/mf_plus/mf_plus_i.h @@ -2,10 +2,9 @@ #include "mf_plus.h" -#define MF_PLUS_FFF_PICC_PREFIX "PICC" +#include -#define MF_PLUS_STATUS_OPERATION_OK (0x90) -#define MF_PLUS_STATUS_ADDITIONAL_FRAME (0xAF) +#define MF_PLUS_FFF_PICC_PREFIX "PICC" MfPlusError mf_plus_get_type_from_version( const Iso14443_4aData* iso14443_4a_data, diff --git a/lib/nfc/protocols/mf_plus/mf_plus_poller_i.c b/lib/nfc/protocols/mf_plus/mf_plus_poller_i.c index cab906f1d..b2e4231ff 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_poller_i.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_poller_i.c @@ -19,28 +19,36 @@ MfPlusError mf_plus_process_error(Iso14443_4aError error) { } } -MfPlusError mf_plus_poller_send_chunk( +MfPlusError mf_plus_process_status_code(uint8_t status_code) { + switch(status_code) { + case NXP_NATIVE_COMMAND_STATUS_OPERATION_OK: + return MfPlusErrorNone; + default: + return MfPlusErrorProtocol; + } +} + +MfPlusError mf_plus_poller_send_chunks( MfPlusPoller* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer) { furi_assert(instance); - furi_assert(instance->iso14443_4a_poller); - furi_assert(instance->tx_buffer); - furi_assert(instance->rx_buffer); - furi_assert(tx_buffer); - furi_assert(rx_buffer); - Iso14443_4aError iso14443_4a_error = iso14443_4a_poller_send_block( - instance->iso14443_4a_poller, tx_buffer, instance->rx_buffer); - MfPlusError error = mf_plus_process_error(iso14443_4a_error); + 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, + NxpNativeCommandModePlain, + instance->tx_buffer, + instance->rx_buffer); - if(error == MfPlusErrorNone) { - bit_buffer_copy(rx_buffer, instance->rx_buffer); + if(iso14443_4a_error != Iso14443_4aErrorNone) { + return mf_plus_process_error(iso14443_4a_error); } - bit_buffer_reset(instance->tx_buffer); - - return error; + return mf_plus_process_status_code(status_code); } MfPlusError mf_plus_poller_read_version(MfPlusPoller* instance, MfPlusVersion* data) { @@ -50,7 +58,7 @@ MfPlusError mf_plus_poller_read_version(MfPlusPoller* instance, MfPlusVersion* d bit_buffer_append_byte(instance->input_buffer, MF_PLUS_CMD_GET_VERSION); MfPlusError error = - mf_plus_poller_send_chunk(instance, instance->input_buffer, instance->result_buffer); + mf_plus_poller_send_chunks(instance, instance->input_buffer, instance->result_buffer); if(error == MfPlusErrorNone) { error = mf_plus_version_parse(data, instance->result_buffer); } diff --git a/lib/nfc/protocols/ntag4xx/ntag4xx.h b/lib/nfc/protocols/ntag4xx/ntag4xx.h index 85dd1e52d..56e5fbd65 100644 --- a/lib/nfc/protocols/ntag4xx/ntag4xx.h +++ b/lib/nfc/protocols/ntag4xx/ntag4xx.h @@ -20,8 +20,6 @@ typedef enum { Ntag4xxErrorNotPresent, Ntag4xxErrorProtocol, Ntag4xxErrorTimeout, - Ntag4xxErrorAuthentication, - Ntag4xxErrorCommandNotSupported, } Ntag4xxError; typedef enum { diff --git a/lib/nfc/protocols/ntag4xx/ntag4xx_i.c b/lib/nfc/protocols/ntag4xx/ntag4xx_i.c index 40f22fc41..b4ee3a9eb 100644 --- a/lib/nfc/protocols/ntag4xx/ntag4xx_i.c +++ b/lib/nfc/protocols/ntag4xx/ntag4xx_i.c @@ -21,12 +21,8 @@ Ntag4xxError ntag4xx_process_error(Iso14443_4aError error) { Ntag4xxError ntag4xx_process_status_code(uint8_t status_code) { switch(status_code) { - case NTAG4XX_STATUS_OPERATION_OK: + case NXP_NATIVE_COMMAND_STATUS_OPERATION_OK: return Ntag4xxErrorNone; - case NTAG4XX_STATUS_AUTHENTICATION_ERROR: - return Ntag4xxErrorAuthentication; - case NTAG4XX_STATUS_ILLEGAL_COMMAND_CODE: - return Ntag4xxErrorCommandNotSupported; default: return Ntag4xxErrorProtocol; } diff --git a/lib/nfc/protocols/ntag4xx/ntag4xx_i.h b/lib/nfc/protocols/ntag4xx/ntag4xx_i.h index db6dabd4b..5a71cf05a 100644 --- a/lib/nfc/protocols/ntag4xx/ntag4xx_i.h +++ b/lib/nfc/protocols/ntag4xx/ntag4xx_i.h @@ -2,44 +2,10 @@ #include "ntag4xx.h" +#include + #define NTAG4XX_FFF_PICC_PREFIX "PICC" -// ISO 7816 command wrapping -#define NTAG4XX_CMD_ISO_CLA (0x90) -#define NTAG4XX_CMD_ISO_P1 (0x00) -#define NTAG4XX_CMD_ISO_P2 (0x00) -#define NTAG4XX_CMD_ISO_LE (0x00) -// ISO 7816 status wrapping -#define NTAG4XX_STATUS_ISO_SW1 (0x91) - -// Successful operation -#define NTAG4XX_STATUS_OPERATION_OK (0x00) -// Command code not supported -#define NTAG4XX_STATUS_ILLEGAL_COMMAND_CODE (0x1C) -// CRC or MAC does not match data Padding bytes not valid -#define NTAG4XX_STATUS_INTEGRITY_ERROR (0x1E) -// Invalid key number specified -#define NTAG4XX_STATUS_NO_SUCH_KEY (0x40) -// Length of command string invalid -#define NTAG4XX_STATUS_LENGTH_ERROR (0x7E) -// Current configuration / status does not allow the requested command -#define NTAG4XX_STATUS_PERMISSION_DENIED (0x9D) -// Value of the parameter(s) invalid -#define NTAG4XX_STATUS_PARAMETER_ERROR (0x9E) -// Currently not allowed to authenticate. Keep trying until full delay is spent -#define NTAG4XX_STATUS_AUTHENTICATION_DELAY (0xAD) -// Current authentication status does not allow the requested command -#define NTAG4XX_STATUS_AUTHENTICATION_ERROR (0xAE) -// Additional data frame is expected to be sent -#define NTAG4XX_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 NTAG4XX_STATUS_BOUNDARY_ERROR (0xBE) -// Previous Command was not fully completed. Not all Frames were requested or provided by the PCD -#define NTAG4XX_STATUS_COMMAND_ABORTED (0xCA) -// Specified file number does not exist -#define NTAG4XX_STATUS_FILE_NOT_FOUND (0xF0) - // Internal helpers Ntag4xxError ntag4xx_process_error(Iso14443_4aError error); diff --git a/lib/nfc/protocols/ntag4xx/ntag4xx_poller_i.c b/lib/nfc/protocols/ntag4xx/ntag4xx_poller_i.c index 9fc53e0a5..5b8b7191d 100644 --- a/lib/nfc/protocols/ntag4xx/ntag4xx_poller_i.c +++ b/lib/nfc/protocols/ntag4xx/ntag4xx_poller_i.c @@ -11,83 +11,22 @@ Ntag4xxError ntag4xx_poller_send_chunks( 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); - Ntag4xxError error = Ntag4xxErrorNone; - uint8_t status_code = NTAG4XX_STATUS_OPERATION_OK; + 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, + NxpNativeCommandModeIsoWrapped, + instance->tx_buffer, + instance->rx_buffer); - do { - bit_buffer_reset(instance->tx_buffer); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_CLA); - bit_buffer_append_byte(instance->tx_buffer, bit_buffer_get_byte(tx_buffer, 0)); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_P1); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_P2); - if(bit_buffer_get_size_bytes(tx_buffer) > 1) { - bit_buffer_append_byte(instance->tx_buffer, bit_buffer_get_size_bytes(tx_buffer) - 1); - bit_buffer_append_right(instance->tx_buffer, tx_buffer, 1); - } - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_LE); - - 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 = ntag4xx_process_error(iso14443_4a_error); - break; - } - - bit_buffer_reset(instance->tx_buffer); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_CLA); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_STATUS_ADDITIONAL_FRAME); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_P1); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_P2); - bit_buffer_append_byte(instance->tx_buffer, NTAG4XX_CMD_ISO_LE); - - size_t response_len = bit_buffer_get_size_bytes(instance->rx_buffer); - status_code = NTAG4XX_STATUS_LENGTH_ERROR; - bit_buffer_reset(rx_buffer); - if(response_len >= 2 * sizeof(uint8_t) && - bit_buffer_get_byte(instance->rx_buffer, response_len - 2) == NTAG4XX_STATUS_ISO_SW1) { - status_code = bit_buffer_get_byte(instance->rx_buffer, response_len - 1); - if(response_len > 2 * sizeof(uint8_t)) { - bit_buffer_copy_left( - rx_buffer, instance->rx_buffer, response_len - 2 * sizeof(uint8_t)); - } - } - - while(status_code == NTAG4XX_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 = ntag4xx_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); - - status_code = rx_size < 2 ? NTAG4XX_STATUS_LENGTH_ERROR : - bit_buffer_get_byte(instance->rx_buffer, rx_size - 1); - if(rx_size <= rx_capacity_remaining + 2) { - bit_buffer_set_size_bytes(instance->rx_buffer, rx_size - 2); - bit_buffer_append(rx_buffer, instance->rx_buffer); - } else { - FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 2); - } - } - } while(false); - - if(error == Ntag4xxErrorNone) { - error = ntag4xx_process_status_code(status_code); + if(iso14443_4a_error != Iso14443_4aErrorNone) { + return ntag4xx_process_error(iso14443_4a_error); } - return error; + return ntag4xx_process_status_code(status_code); } Ntag4xxError ntag4xx_poller_read_version(Ntag4xxPoller* instance, Ntag4xxVersion* data) { diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c index e9bbfffc0..4722a169d 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c @@ -239,7 +239,7 @@ Type4TagError type_4_tag_poller_detect_platform(Type4TagPoller* instance) { FURI_LOG_D(TAG, "Detect DESFire"); MfDesfirePoller* mf_desfire = mf_desfire_poller.alloc(instance->iso14443_4a_poller); - mf_desfire_poller_set_command_mode(mf_desfire, MfDesfirePollerCommandModeIsoWrapped); + mf_desfire_poller_set_command_mode(mf_desfire, NxpNativeCommandModeIsoWrapped); if(mf_desfire_poller.detect(event, mf_desfire)) { platform = Type4TagPlatformMfDesfire; nfc_device_set_data( @@ -349,7 +349,7 @@ Type4TagError type_4_tag_poller_create_app(Type4TagPoller* instance) { if(instance->data->platform == Type4TagPlatformMfDesfire) { MfDesfirePoller* mf_des = mf_desfire_poller.alloc(instance->iso14443_4a_poller); - mf_desfire_poller_set_command_mode(mf_des, MfDesfirePollerCommandModeIsoWrapped); + mf_desfire_poller_set_command_mode(mf_des, NxpNativeCommandModeIsoWrapped); MfDesfireError mf_des_error; do { @@ -392,7 +392,7 @@ Type4TagError type_4_tag_poller_create_cc(Type4TagPoller* instance) { if(instance->data->platform == Type4TagPlatformMfDesfire) { MfDesfirePoller* mf_des = mf_desfire_poller.alloc(instance->iso14443_4a_poller); - mf_desfire_poller_set_command_mode(mf_des, MfDesfirePollerCommandModeIsoWrapped); + mf_desfire_poller_set_command_mode(mf_des, NxpNativeCommandModeIsoWrapped); MfDesfireError mf_des_error; do { @@ -441,7 +441,7 @@ Type4TagError type_4_tag_poller_create_ndef(Type4TagPoller* instance) { if(instance->data->platform == Type4TagPlatformMfDesfire) { MfDesfirePoller* mf_des = mf_desfire_poller.alloc(instance->iso14443_4a_poller); - mf_desfire_poller_set_command_mode(mf_des, MfDesfirePollerCommandModeIsoWrapped); + mf_desfire_poller_set_command_mode(mf_des, NxpNativeCommandModeIsoWrapped); MfDesfireError mf_des_error; do { diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 385b687dc..a221aa708 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2657,7 +2657,7 @@ Function,+,mf_desfire_poller_read_key_versions,MfDesfireError,"MfDesfirePoller*, Function,+,mf_desfire_poller_read_version,MfDesfireError,"MfDesfirePoller*, MfDesfireVersion*" Function,+,mf_desfire_poller_select_application,MfDesfireError,"MfDesfirePoller*, const MfDesfireApplicationId*" Function,+,mf_desfire_poller_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*" -Function,+,mf_desfire_poller_set_command_mode,void,"MfDesfirePoller*, MfDesfirePollerCommandMode" +Function,+,mf_desfire_poller_set_command_mode,void,"MfDesfirePoller*, NxpNativeCommandMode" Function,+,mf_desfire_reset,void,MfDesfireData* Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*" Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t"