Files

378 lines
11 KiB
C

/** 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