/** Functions to support interfacing with NXP tags * * This header defines functions for working with ISO14443-3 compliant NXP * PICCs, primarily the Ultralight and NTAG families. These PICCs use * predominately the same command set, with some small variations. * * For MIFARE Classic PICCs, see `include/picc/rc522_mifare.h`. * * Authentication: * Ultralight {C,AES}: Key-based (3DES and AES respectively) * Ultralight EV1, NTAG 21x: Password-based * * Some functions have been commented out; ideally these would be implemented * at some stage to implement full support for these PICC functions, but I don't * have any of the actual PICCs to properly test with. * * CMD/PICC | UL | UL C | UL EV1 | UL AES | UL Nano | NTAG21x | * -------------|---------|---------|---------|---------|---------|---------| * GET_VERSION | | | y | y | y | y | * READ | y | y | y | y | y | y | * FAST_READ | | | y | y | | y | * WRITE | y | y | y | y | y | y | * COMPAT_WRITE | y | y | y | | y | y | * READ_CNT | | | 3 | 3 | | 1 | * INCR_CNT | | | y | y | | | * READ_SIG | | | 32 | 48 | 32 | 32 | (bytes) * WRITE_SIG | | | | y | y | | * LOCK_SIG | | | | y | y | | * AUTHENTICATE | | 3DES | | AES | | | * PWD_AUTH | | | y | | | y | * VCSL | | | y | y | | | */ #pragma once #include "rc522_picc.h" #include "rc522_types.h" #ifdef __cplusplus extern "C" { #endif #define RC522_ERR_NXP_BASE (RC522_ERR_BASE + 0XF0) #define RC522_ERR_NXP_NACK (RC522_ERR_NXP_BASE + 1) #define RC522_ERR_NXP_AUTHENTICATION_FAILED (RC522_ERR_NXP_BASE + 2) #define RC522_ERR_NXP_PACK_MISMATCH (RC522_ERR_NXP_BASE + 3) #define RC522_NXP_PWD_SIZE 4 #define RC522_NXP_PACK_SIZE 2 #define RC522_NXP_PAGE_SIZE 4 #define RC522_NXP_READ_SIZE (RC522_NXP_PAGE_SIZE * 4) extern const uint8_t RC522_NXP_DEFAULT_PWD[RC522_NXP_PWD_SIZE]; extern const uint8_t RC522_NXP_DEFAULT_PACK[RC522_NXP_PACK_SIZE]; enum { /** * Get PICC information. */ RC522_NXP_GET_VERSION = 0x60, /** * Read four pages from memory. */ RC522_NXP_READ = 0x30, /** * Read pages from START to END in memory. */ RC522_NXP_FAST_READ = 0x3A, /** * Write a page to memory. */ RC522_NXP_WRITE = 0xA2, /** * Write the first 4 bytes of 16 to a page in memory. */ RC522_NXP_COMPAT_WRITE = 0xA0, /** * Read an onboard counter. */ RC522_NXP_READ_CNT = 0x39, /** * Increment an onboard counter. */ RC522_NXP_INCR_CNT = 0xA5, /** * Read the originality signature. */ RC522_NXP_READ_SIG = 0x3C, /** * Write a new originality signature. */ RC522_NXP_WRITE_SIG = 0xA9, /** * Control access to the originality signature. */ RC522_NXP_LOCK_SIG = 0xAC, /** * Perform key-based authentication, stage 1. */ RC522_NXP_AUTHENTICATE = 0x1A, /** * Perform key-based authentication, stage 2. */ RC522_NXP_AUTHENTICATE_2 = 0xAF, /** * Perform password-based authentication. */ RC522_NXP_PWD_AUTH = 0x1B, RC522_NXP_VCSL = 0x4B, }; /** * L3 GET_VERSION: product_type field */ typedef enum { RC522_NXP_PRODUCT_TYPE_UNKNOWN, RC522_NXP_PRODUCT_TYPE_UL = 0x03, RC522_NXP_PRODUCT_TYPE_NTAG = 0x04, } rc522_nxp_product_type_t; /** * L3 GET_VERSION: major_version field */ typedef enum { RC522_NXP_MAJ_VER_UNKNOWN = 0, RC522_NXP_MAJ_VER_NTAG21 = 0x01, RC522_NXP_MAJ_VER_UL_EV1 = 0x01, RC522_NXP_MAJ_VER_UL_NANO = 0x02, RC522_NXP_MAJ_VER_UL_AES = 0x04, } rc522_nxp_major_version_t; /** * L3 GET_VERSION result */ typedef struct { uint8_t header; uint8_t vendor; rc522_nxp_product_type_t product_type :8; uint8_t product_subtype; rc522_nxp_major_version_t major_version :8; uint8_t minor_version; uint8_t storage_size; uint8_t protocol_type; } rc522_nxp_picc_version_t; /** * L3 FAST_READ result * * Contains a buffer, the size of the buffer, and the amount of space occupied * by the data after a read */ typedef struct { uint8_t *bytes; uint8_t buffer_size; uint8_t read_size; } rc522_nxp_fast_read_data_t; /** * Variable-length protection signature * * UL EV1: 32 bytes * UL AES: 48 bytes * UL Nano: 32 bytes * NTAG213/215/216: 32 bytes */ typedef struct { uint8_t *bytes; uint8_t buffer_size; uint8_t sig_size; } rc522_nxp_sig_t; /** * @brief Determine the total memory size of an NXP PICC * * Given an NXP PICC type, returns the total size of the memory in pages. This * is not equivalent to generic user memory. * * For invalid types, unknown types, or types without pages, returns 0. * * @sa rc522_nxp_get_user_page_count() */ uint8_t rc522_nxp_get_page_count(rc522_picc_type_t type); /** * @brief Determine the user memory size of an NXP PICC * * Given an NXP PICC type (RC522_PICC_TYPE_MIFARE_UL_* or RC522_PICC_TYPE_NTAG*), * returns the total size of the user memory in pages. The user memory always * starts at page 4. * * For invalid types, unknown types, or types without pages, returns 0. */ uint8_t rc522_nxp_get_user_page_count(rc522_picc_type_t type); /** * @brief Determine the start page of user memory for an NXP PICC * * Currently this is 0x04 for all PICCs. It's unlikely to change in future * for compatibility reasons, but this function exists in case (and also * as a reference). * * For invalid or unknown types, returns 0. */ uint8_t rc522_nxp_get_user_mem_start(rc522_picc_type_t type); /** * @brief Determine the final page of user memory for an NXP PICC * * Returns the address of the final page of user memory for a given PICC * type. This is the last page that can be safely written to without changing * the configuration of the PICC. * * For invalid or unknown types, returns 0. */ uint8_t rc522_nxp_get_user_mem_end(rc522_picc_type_t type); /** * @brief Determine the type of an NXP PICC * * The Ultralight and NTAG families both use SAK=0, and need further processing * to identify. This function attempts to determine the PICC in use following * the procedure in NXP Application Note 10833. */ esp_err_t rc522_nxp_get_type(const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_picc_type_t *out_type); /** * @brief NXP Level 3 GET_VERSION * * If supported, returns information about the PICC, including manufacturer, * product, and memory size. */ esp_err_t rc522_nxp_get_version( const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_nxp_picc_version_t *out_version); /** * @brief NXP Level 3 READ * * Reads 4 pages (16 bytes) from a given page address on the PICC. */ esp_err_t rc522_nxp_read( const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t address, uint8_t out_buffer[RC522_NXP_PAGE_SIZE * 4]); /** * NXP Level 3 FAST_READ * * If supported, allows a variable number of pages to be read at once, instead * of the fixed 4 in READ. * * @param start Page address to start reading from * @param end Page address to end reading (inclusive) * @param out_buffer Output buffer; should be at least (end-start+1) * 4 bytes * * Supported PICCs: UL EV1, UL AES, NTAG21x */ esp_err_t rc522_nxp_fast_read(const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t start, uint8_t end, rc522_nxp_fast_read_data_t *out_buffer); /** * @brief NXP Level 3 WRITE * * Writes 4 bytes of data to a single page. */ esp_err_t rc522_nxp_write( const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t address, const uint8_t buffer[RC522_NXP_PAGE_SIZE]); /** * @brief NXP Level 3 READ_CNT * * If supported, reads a counter from the PICC. Some PICCs have more than one * counter; if so counter_no specifies the counter to address. * * Supported PICCs: UL EV1 (3), UL AES (3), NTAG21x (1) */ esp_err_t rc522_nxp_read_cnt( const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t counter_no, uint32_t *out_count); /** * @brief NXP Level 3 INCR_CNT * * If supported, increments a counter on the PICC. If the PICC has more than one * counter, counter_no specifies the counter to target. * * TODO */ // esp_err_t rc522_nxp_incr_cnt(const rc522_handle_t rc522, const rc522_picc_t *picc, // uint8_t counter_no); /** * @brief Checks for support for AUTHENTICATE in L3 on a PICC * * Used to determine if a chip supports AUTHENTICATE, to differentiate between * Ultralight and Ultralight C. Does not perform actual authentication. */ esp_err_t rc522_nxp_keyauth_supported(const rc522_handle_t rc522, const rc522_picc_t *picc); /** * @brief NXP Level 3 AUTHENTICATE * * If supported, performs key-based authentication with a PICC. Note support * for DES and/or AES algorithms is required. * * TODO */ // esp_err_t rc522_nxp_key_auth(const rc522_handle_t rc522, const rc522_picc_t *picc, // rc522_nxp_key_t *key); /** * @brief NXP Level 3 PWD_AUTH * * If supported, performs password-based authentication with a PICC. * * @param pwd Password to send to pick * @param pack Password ACKnowledgement expected to be returned by PICC * @param[out] out_state PICC state on return. Correct PWD with mismatched PACK * will still result in AUTHENTICATED * * Supported PICCs: UL EV1, NTAG21x */ esp_err_t rc522_nxp_pwd_auth(const rc522_handle_t rc522, const rc522_picc_t *picc, const uint8_t pwd[RC522_NXP_PWD_SIZE], const uint8_t pack[RC522_NXP_PACK_SIZE], rc522_picc_state_t *out_state); /** * @brief NXP Level 3 READ_SIG * * If supported, reads the ECC signature from the PICC. This signature can * be used to verify originality. Does not actually perform verification. * * TODO: Implement verification per AN11350? * * Supported PICCs: UL EV1, UL AES, UL Nano, NTAG21x */ esp_err_t rc522_nxp_read_sig(const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_nxp_sig_t *out_sig); /** * @brief NXP Level 3 WRITE_SIG * * If supported, writes a new signature to the PICC. * * TODO */ // esp_err_t rc522_nxp_write_sig(const rc522_handle_t rc522, const rc522_picc_t *picc, // rc522_nxp_sig_t *sig); /** * @brief NXP Level 3 LOCK_SIG * * If supported, controls the originality signature lock on the PICC. * * @param argument 0x00 for unlock, 0x01 for lock, 0x02 for permanent lock * * TODO */ // esp_err_t rc522_nxp_lock_sig(const rc522_handle_t rc522, const rc522_picc_t *picc, // rc522_nxp_sig_arg_t argument); #ifdef __cplusplus } #endif