1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-13 13:09:49 +04:00
Files
unleashed-firmware/lib/nfc/protocols/felica/felica.h
RebornedBrain fb9728d570 [FL-3772] Felica poller (#3570)
* New types for felica poller
* New functions for felica data transmissions
* Felica memory map extended with new fields
* Init/deinit of mbedtls context added for felica encryption
* Functions for session key and mac calculations added
* Raw felica_poller implementation added
* Removed MAC type parameter from check_mac function
* Replaced all data fields needed for auth with context structure
* Clean up felica_poller.c
* Now RC block is filled with random numbers
* New parameter for counting well-read blocks
* Some cleanups
* Felica file save and load logic added
* Now we use card key from context for session key calculation
* Copying card key to card block from auth context when both authentications succeeded, otherwise decrement blocks count by 1
* New felica poller event added
* Moved some data structions to public namespace
* FelicaAuthenticationContext struct moved to felica.h
* Field type and name changed for better ones
* Helper functions for felica_auth added to the app
* New scene for felica card key input added
* Logic for felica key input added
* Auth context request processing added
* Added block index definitions and replaced all index numbers with them
* More macro defines
* Replace nesting with do while block
* New function for write operations mac calculation added
* Replace nesting with do while block
* Make functions static for now because they are used internally
* Wrote some comments
* Raw felica render implementation
* New felica scenes
* Adjusted felica dump rendering according design requirements
* New felica scene added
* Helper for switching scene during unlock added
* Added warning scene and transfer to it
* Moved unlock scene logic to separate files
* Magic number changed
* New felica render logic
* Felica scenes adjusted according to design requirements
* Felica poller cleanups
* Some asserts added and some fixed
* Replcaed asserts to checks in public api
* Fixed pvs warnings in felica_poller
* New event for felica_poller added for incomplete read actions
* Handling of new poller event added
* Update SConscript with felica files
* Update api_symbols.csv with felica functions
* Sync API versions

Co-authored-by: あく <alleteam@gmail.com>
2024-04-10 18:51:36 +09:00

181 lines
5.1 KiB
C

#pragma once
#include <toolbox/bit_buffer.h>
#include <nfc/protocols/nfc_device_base_i.h>
#include <mbedtls/include/mbedtls/des.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FELICA_IDM_SIZE (8U)
#define FELICA_PMM_SIZE (8U)
#define FELICA_DATA_BLOCK_SIZE (16U)
#define FELICA_BLOCKS_TOTAL_COUNT (27U)
#define FELICA_BLOCK_INDEX_REG (0x0EU)
#define FELICA_BLOCK_INDEX_RC (0x80U)
#define FELICA_BLOCK_INDEX_MAC (0x81U)
#define FELICA_BLOCK_INDEX_ID (0x82U)
#define FELICA_BLOCK_INDEX_D_ID (0x83U)
#define FELICA_BLOCK_INDEX_SER_C (0x84U)
#define FELICA_BLOCK_INDEX_SYS_C (0x85U)
#define FELICA_BLOCK_INDEX_CKV (0x86U)
#define FELICA_BLOCK_INDEX_CK (0x87U)
#define FELICA_BLOCK_INDEX_MC (0x88U)
#define FELICA_BLOCK_INDEX_WCNT (0x90U)
#define FELICA_BLOCK_INDEX_MAC_A (0x91U)
#define FELICA_BLOCK_INDEX_STATE (0x92U)
#define FELICA_BLOCK_INDEX_CRC_CHECK (0xA0U)
#define FELICA_GUARD_TIME_US (20000U)
#define FELICA_FDT_POLL_FC (10000U)
#define FELICA_POLL_POLL_MIN_US (1280U)
#define FELICA_FDT_LISTEN_FC (1172)
#define FELICA_SYSTEM_CODE_CODE (0xFFFFU)
#define FELICA_TIME_SLOT_1 (0x00U)
#define FELICA_TIME_SLOT_2 (0x01U)
#define FELICA_TIME_SLOT_4 (0x03U)
#define FELICA_TIME_SLOT_8 (0x07U)
#define FELICA_TIME_SLOT_16 (0x0FU)
/** @brief Type of possible Felica errors */
typedef enum {
FelicaErrorNone,
FelicaErrorNotPresent,
FelicaErrorColResFailed,
FelicaErrorBufferOverflow,
FelicaErrorCommunication,
FelicaErrorFieldOff,
FelicaErrorWrongCrc,
FelicaErrorProtocol,
FelicaErrorTimeout,
} FelicaError;
/** @brief Separate type for card key block. Used in authentication process */
typedef struct {
uint8_t data[FELICA_DATA_BLOCK_SIZE];
} FelicaCardKey;
/** @brief In Felica there two types of auth. Internal is the first one, after
* which external became possible. Here are two flags representing which one
* was passed */
typedef struct {
bool internal : 1;
bool external : 1;
} FelicaAuthenticationStatus;
/** @brief Struct which controls the process of authentication and can be passed as
* a parameter to the application level. In order to force user to fill card key block data. */
typedef struct {
bool skip_auth; /**< By default it is true, so auth is skipped. By setting this to false several auth steps will be performed in order to pass auth*/
FelicaCardKey
card_key; /**< User must fill this field with known card key in order to pass auth*/
FelicaAuthenticationStatus auth_status; /**< Authentication status*/
} FelicaAuthenticationContext;
/** @brief Felica ID block */
typedef struct {
uint8_t data[FELICA_IDM_SIZE];
} FelicaIDm;
/** @brief Felica PMm block */
typedef struct {
uint8_t data[FELICA_PMM_SIZE];
} FelicaPMm;
/** @brief Felica block with status flags indicating last operation with it.
* See Felica manual for more details on status codes. */
typedef struct {
uint8_t SF1; /**< Status flag 1, equals to 0 when success*/
uint8_t SF2; /**< Status flag 2, equals to 0 when success*/
uint8_t data[FELICA_DATA_BLOCK_SIZE]; /**< Block data */
} FelicaBlock;
/** @brief Felica filesystem structure */
typedef struct {
FelicaBlock spad[14];
FelicaBlock reg;
FelicaBlock rc;
FelicaBlock mac;
FelicaBlock id;
FelicaBlock d_id;
FelicaBlock ser_c;
FelicaBlock sys_c;
FelicaBlock ckv;
FelicaBlock ck;
FelicaBlock mc;
FelicaBlock wcnt;
FelicaBlock mac_a;
FelicaBlock state;
FelicaBlock crc_check;
} FelicaFileSystem;
/** @brief Union which represents filesystem in junction with plain data dump */
typedef union {
FelicaFileSystem fs;
uint8_t dump[sizeof(FelicaFileSystem)];
} FelicaFSUnion;
/** @brief Structure used to store Felica data and additional values about reading */
typedef struct {
FelicaIDm idm;
FelicaPMm pmm;
uint8_t blocks_total;
uint8_t blocks_read;
FelicaFSUnion data;
} FelicaData;
extern const NfcDeviceBase nfc_device_felica;
FelicaData* felica_alloc(void);
void felica_free(FelicaData* data);
void felica_reset(FelicaData* data);
void felica_copy(FelicaData* data, const FelicaData* other);
bool felica_verify(FelicaData* data, const FuriString* device_type);
bool felica_load(FelicaData* data, FlipperFormat* ff, uint32_t version);
bool felica_save(const FelicaData* data, FlipperFormat* ff);
bool felica_is_equal(const FelicaData* data, const FelicaData* other);
const char* felica_get_device_name(const FelicaData* data, NfcDeviceNameType name_type);
const uint8_t* felica_get_uid(const FelicaData* data, size_t* uid_len);
bool felica_set_uid(FelicaData* data, const uint8_t* uid, size_t uid_len);
FelicaData* felica_get_base_data(const FelicaData* data);
void felica_calculate_session_key(
mbedtls_des3_context* ctx,
const uint8_t* ck,
const uint8_t* rc,
uint8_t* out);
bool felica_check_mac(
mbedtls_des3_context* ctx,
const uint8_t* session_key,
const uint8_t* rc,
const uint8_t* blocks,
const uint8_t block_count,
uint8_t* data);
void felica_calculate_mac_write(
mbedtls_des3_context* ctx,
const uint8_t* session_key,
const uint8_t* rc,
const uint8_t* wcnt,
const uint8_t* data,
uint8_t* mac);
#ifdef __cplusplus
}
#endif