From 6e669fd867afaaca3ab45deaefea1f2a13998998 Mon Sep 17 00:00:00 2001 From: cburandt Date: Fri, 20 Dec 2024 12:40:57 +0200 Subject: [PATCH] Add module for NXP PN7160 NFC chip as token provider (#951) * Add module for PN7160 NFC reader Signed-off-by: Christoph Burandt * Refactor Code to meet criteria of PR discussion: Signed-off-by: Christoph Burandt * Add debug config option and log token discovery only in debug mode Signed-off-by: Christoph Burandt * Set configuration file search path at runtime Signed-off-by: Christoph Burandt --------- Signed-off-by: Christoph Burandt Signed-off-by: cburandt --- CMakeLists.txt | 1 + dependencies.yaml | 5 + module-dependencies.cmake | 5 + modules/CMakeLists.txt | 1 + modules/PN7160TokenProvider/CMakeLists.txt | 41 ++++ .../PN7160TokenProvider.cpp | 15 ++ .../PN7160TokenProvider.hpp | 58 +++++ modules/PN7160TokenProvider/doc.rst | 27 +++ .../libnfc-nci_config/libnfc-nci.conf | 121 ++++++++++ .../libnfc-nci_config/libnfc-nxp.conf | 221 ++++++++++++++++++ .../main/auth_token_providerImpl.cpp | 85 +++++++ .../main/auth_token_providerImpl.hpp | 72 ++++++ .../main/libnfc_handler.cpp | 90 +++++++ .../main/libnfc_handler.hpp | 33 +++ modules/PN7160TokenProvider/manifest.yaml | 28 +++ 15 files changed, 803 insertions(+) create mode 100644 modules/PN7160TokenProvider/CMakeLists.txt create mode 100644 modules/PN7160TokenProvider/PN7160TokenProvider.cpp create mode 100644 modules/PN7160TokenProvider/PN7160TokenProvider.hpp create mode 100644 modules/PN7160TokenProvider/doc.rst create mode 100644 modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nci.conf create mode 100644 modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nxp.conf create mode 100644 modules/PN7160TokenProvider/main/auth_token_providerImpl.cpp create mode 100644 modules/PN7160TokenProvider/main/auth_token_providerImpl.hpp create mode 100644 modules/PN7160TokenProvider/main/libnfc_handler.cpp create mode 100644 modules/PN7160TokenProvider/main/libnfc_handler.hpp create mode 100644 modules/PN7160TokenProvider/manifest.yaml diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a266734f..9d6fb7f56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ else() find_package(fsm REQUIRED) find_package(slac REQUIRED) + find_package(libnfc-nci REQUIRED) find_package(pugixml REQUIRED) find_package(CURL 7.84.0 REQUIRED) diff --git a/dependencies.yaml b/dependencies.yaml index 02c6a2194..c47f36fb4 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -87,6 +87,11 @@ ext-mbedtls: everest-utils: git: https://github.com/EVerest/everest-utils.git git_tag: v0.4.4 +# linux_libnfc-nci for RFID +libnfc-nci: + git: https://github.com/EVerest/linux_libnfc-nci.git + git_tag: 2024.11.0 + cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBNFC_NCI" # unit testing gtest: diff --git a/module-dependencies.cmake b/module-dependencies.cmake index de3c28095..9f4706b73 100644 --- a/module-dependencies.cmake +++ b/module-dependencies.cmake @@ -58,6 +58,11 @@ ev_define_dependency( OUTPUT_VARIABLE_SUFFIX LIBISO15118 DEPENDENT_MODULES_LIST Evse15118D20) +ev_define_dependency( + DEPENDENCY_NAME libnfc-nci + OUTPUT_VARIABLE_SUFFIX LIBNFC_NCI + DEPENDENT_MODULES_LIST PN7160TokenProvider) + if(NOT everest-gpio IN_LIST EVEREST_EXCLUDE_DEPENDENCIES) set(EVEREST_DEPENDENCY_ENABLED_EVEREST_GPIO ON) else() diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index beb2e4608..57c02f36c 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -19,6 +19,7 @@ ev_add_module(OCPP201) ev_add_module(PacketSniffer) ev_add_module(PersistentStore) ev_add_module(PN532TokenProvider) +ev_add_module(PN7160TokenProvider) ev_add_module(PyEvJosev) ev_add_module(Setup) ev_add_module(SerialCommHub) diff --git a/modules/PN7160TokenProvider/CMakeLists.txt b/modules/PN7160TokenProvider/CMakeLists.txt new file mode 100644 index 000000000..584f2f405 --- /dev/null +++ b/modules/PN7160TokenProvider/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# AUTO GENERATED - MARKED REGIONS WILL BE KEPT +# template version 3 +# + +# module setup: +# - ${MODULE_NAME}: module name +ev_setup_cpp_module() + +# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1 + +target_include_directories(${MODULE_NAME} +PRIVATE + "common" +) + +target_sources(${MODULE_NAME} + PRIVATE + "main/libnfc_handler.cpp" +) + +target_link_libraries(${MODULE_NAME} + PRIVATE + "libnfc_nci" +) +# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1 + +target_sources(${MODULE_NAME} + PRIVATE + "main/auth_token_providerImpl.cpp" +) + +# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 + +install(FILES + "libnfc-nci_config/libnfc-nxp.conf" + "libnfc-nci_config/libnfc-nci.conf" + DESTINATION + "${CMAKE_INSTALL_SYSCONFDIR}/everest/libnfc_config/") + +# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/PN7160TokenProvider/PN7160TokenProvider.cpp b/modules/PN7160TokenProvider/PN7160TokenProvider.cpp new file mode 100644 index 000000000..dc95428be --- /dev/null +++ b/modules/PN7160TokenProvider/PN7160TokenProvider.cpp @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 - 2024 Pionix GmbH and Contributors to EVerest +#include "PN7160TokenProvider.hpp" + +namespace module { + +void PN7160TokenProvider::init() { + invoke_init(*p_main); +} + +void PN7160TokenProvider::ready() { + invoke_ready(*p_main); +} + +} // namespace module diff --git a/modules/PN7160TokenProvider/PN7160TokenProvider.hpp b/modules/PN7160TokenProvider/PN7160TokenProvider.hpp new file mode 100644 index 000000000..88ffeff72 --- /dev/null +++ b/modules/PN7160TokenProvider/PN7160TokenProvider.hpp @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest +#ifndef PN7160TOKEN_PROVIDER_HPP +#define PN7160TOKEN_PROVIDER_HPP + +// +// AUTO GENERATED - MARKED REGIONS WILL BE KEPT +// template version 2 +// + +#include "ld-ev.hpp" + +// headers for provided interface implementations +#include + +// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 +// insert your custom include headers here +// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 + +namespace module { + +struct Conf {}; + +class PN7160TokenProvider : public Everest::ModuleBase { +public: + PN7160TokenProvider() = delete; + PN7160TokenProvider(const ModuleInfo& info, std::unique_ptr p_main, Conf& config) : + ModuleBase(info), p_main(std::move(p_main)), config(config){}; + + const std::unique_ptr p_main; + const Conf& config; + + // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 + // insert your public definitions here + // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 + +protected: + // ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1 + // insert your protected definitions here + // ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1 + +private: + friend class LdEverest; + void init(); + void ready(); + + // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 + // insert your private definitions here + // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 +}; + +// ev@087e516b-124c-48df-94fb-109508c7cda9:v1 +// insert other definitions here +// ev@087e516b-124c-48df-94fb-109508c7cda9:v1 + +} // namespace module + +#endif // PN7160TOKEN_PROVIDER_HPP diff --git a/modules/PN7160TokenProvider/doc.rst b/modules/PN7160TokenProvider/doc.rst new file mode 100644 index 000000000..e6bb30314 --- /dev/null +++ b/modules/PN7160TokenProvider/doc.rst @@ -0,0 +1,27 @@ +.. _everest_modules_handwritten_PN7160TokenProvider: + +******************* +PN7160TokenProvider +******************* + +This module provides authentication tokens obtained from RFID cards via the NXP PN7160 NFC chip. + +It uses a modified *libnfc-nci* as external dependency to interface the chip via I²C or SPI, either from user space or via a kernel module. + +Hardware Interface Configuration +================================ + +Configuration of the hardware interface is possible at runtime. +The module installs two configuration files: + +* ``libnfc-nci_config/libnfc-nci.conf``: define NFC options +* ``libnfc-nci_config/libnfc-nxp.conf``: choose the hardware interface (kernel module vs. userspace; I²C vs. SPI, ...) + +Module Configuration +==================== + +The EVerest module can be adjusted in its behaviour as follows: + +* ``token_debounce_interval_ms``: Publish tokens in minimum intervall of this timespan in order not to flood subscribers. +* ``disable_nfc_rfid``: Allows to load the module without actually initializing the hardware. + diff --git a/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nci.conf b/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nci.conf new file mode 100644 index 000000000..389abfd87 --- /dev/null +++ b/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nci.conf @@ -0,0 +1,121 @@ +############################################################################## +# +# Note by PIONIX GmbH +# =================== +# +# Original file distributed NXP +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## + +########################### PN7160 libnfc-nci.conf ############################ + +############################################################################### +# Application options +APPL_TRACE_LEVEL=0xFF +PROTOCOL_TRACE_LEVEL=0xFFFFFFFF + +NFC_DEBUG_ENABLED=0x00 + +############################################################################### +# File used for NFA storage +NFA_STORAGE="/data/vendor/nfc" + +############################################################################### +# Forcing HOST to listen for a selected protocol +# 0x00 : Disable Host Listen +# 0x01 : Enable Host to Listen (A) for ISO-DEP tech A +# 0x02 : Enable Host to Listen (B) for ISO-DEP tech B +# 0x04 : Enable Host to Listen (F) for T3T Tag Type Protocol tech F +# 0x07 : Enable Host to Listen (ABF)for ISO-DEP tech AB & T3T Tag Type Protocol tech F +HOST_LISTEN_TECH_MASK=0x07 + +############################################################################### +# When screen is turned off, specify the desired power state of the controller. +# 0: power-off-sleep state; DEFAULT +# 1: full-power state +# 2: screen-off card-emulation (CE4/CE3/CE1 modes are used) +SCREEN_OFF_POWER_STATE=1 + +############################################################################### +# NCI Hal Module name +NCI_HAL_MODULE="nfc_nci.pn54x" + +############################################################################### +# Force tag polling for the following technology(s). +# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h. +# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | +# NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ISO15693 | +# NFA_TECHNOLOGY_MASK_KOVIO | NFA_TECHNOLOGY_MASK_A_ACTIVE | +# NFA_TECHNOLOGY_MASK_F_ACTIVE +# +# Notable bits: +# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */ +# NFA_TECHNOLOGY_MASK_B 0x02 /* NFC Technology B */ +# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */ +# NFA_TECHNOLOGY_MASK_ISO15693 0x08 /* Proprietary Technology */ +# NFA_TECHNOLOGY_MASK_KOVIO 0x20 /* Proprietary Technology */ +# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */ +# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */ +# This flag when set to zero will disable Reader mode. +POLLING_TECH_MASK=0xCF + +############################################################################### +# Force P2P to only listen for the following technology(s). +# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h. +# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F | +# NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE +# +# Notable bits: +# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */ +# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */ +# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */ +# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */ +# This flag when set to zero will disable P2P Listen mode. +P2P_LISTEN_TECH_MASK=0xC5 + +PRESERVE_STORAGE=0x01 + +############################################################################### +# AID_MATCHING constants +# AID_MATCHING_EXACT_ONLY 0x00 +# AID_MATCHING_EXACT_OR_PREFIX 0x01 +# AID_MATCHING_PREFIX_ONLY 0x02 +# AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX 0x03 +AID_MATCHING_MODE=0x03 + +############################################################################### +# Override the stack default for NFA_EE_MAX_EE_SUPPORTED set in nfc_target.h. +# Maximum EE supported number +NFA_MAX_EE_SUPPORTED=0x01 + +############################################################################### +#Set the OffHost AID supported power state: +OFFHOST_AID_ROUTE_PWR_STATE=0x3B + +############################################################################### +# Vendor Specific Proprietary Protocol & Discovery Configuration +# Set to 0xFF if unsupported +# byte[0] NCI_PROTOCOL_18092_ACTIVE +# byte[1] NCI_PROTOCOL_B_PRIME +# byte[2] NCI_PROTOCOL_DUAL +# byte[3] NCI_PROTOCOL_15693 +# byte[4] NCI_PROTOCOL_KOVIO +# byte[5] NCI_PROTOCOL_MIFARE +# byte[6] NCI_DISCOVERY_TYPE_POLL_KOVIO +# byte[7] NCI_DISCOVERY_TYPE_POLL_B_PRIME +# byte[8] NCI_DISCOVERY_TYPE_LISTEN_B_PRIME +NFA_PROPRIETARY_CFG={05:FF:FF:06:81:80:70:FF:FF} + +############################################################################### diff --git a/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nxp.conf b/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nxp.conf new file mode 100644 index 000000000..f32cd8dc9 --- /dev/null +++ b/modules/PN7160TokenProvider/libnfc-nci_config/libnfc-nxp.conf @@ -0,0 +1,221 @@ +############################################################################## +# +# Note by PIONIX GmbH +# =================== +# +# Original file distributed NXP +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# -------------------------------------------------------- +# This file has been changed by PIONIX GmbH in 11-2024 +# Changes are marked below +# -------------------------------------------------------- +# +############################################################################## + +########################### PN7160 libnfc-nxp.conf ############################ + +############################################################################### +# Logging Levels. Suggested value for debugging is 0x03. +# NXPLOG_GLOBAL_LOGLEVEL - Configuration for Global logging level +# NXPLOG_EXTNS_LOGLEVEL - Configuration for extns logging level +# NXPLOG_NCIHAL_LOGLEVEL - Configuration for enabling logging of HAL +# NXPLOG_NCIX_LOGLEVEL - Configuration for enabling logging of NCI TX packets +# NXPLOG_NCIR_LOGLEVEL - Configuration for enabling logging of NCI RX packets +# NXPLOG_FWDNLD_LOGLEVEL - Configuration for enabling logging of FW download functionality +# NXPLOG_TML_LOGLEVEL - Configuration for enabling logging of TML +# Logging Levels +# NXPLOG_DEFAULT_LOGLEVEL 0x01 +# NXPLOG_DEBUG_LOGLEVEL 0x03 +# NXPLOG_WARN_LOGLEVEL 0x02 +# NXPLOG_ERROR_LOGLEVEL 0x01 +# NXPLOG_SILENT_LOGLEVEL 0x00 +NXPLOG_EXTNS_LOGLEVEL=0x00 +NXPLOG_NCIHAL_LOGLEVEL=0x00 +NXPLOG_NCIX_LOGLEVEL=0x00 +NXPLOG_NCIR_LOGLEVEL=0x00 +NXPLOG_FWDNLD_LOGLEVEL=0x00 +NXPLOG_TML_LOGLEVEL=0x00 +############################################################################### +# TRANSPORT Type +# 0x00 - I2C /SPI for noraml nxpnfc driver +# 0x01 - Not Used, kept to align with Android code +# 0x02 - ALT_I2C +# 0x03 - ALT_SPI +NXP_TRANSPORT=0x02 + +############################################################################### +# Nfc Device Node name +NXP_NFC_DEV_NODE="/dev/nxpnfc" + +# Modification by PIONIX GmbH 2024 vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +############################################################################### +# ALT_I2C/SPI Interface Configuration +# [PINs defined as GPIO23/24/25 on RPi5] +PIN_INT=594 +PIN_ENABLE=595 +PIN_FWDNLD=596 + +I2C_ADDRESS=0x28 +I2C_BUS="/dev/i2c-1" +SPI_BUS="/dev/spidev0.0" +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +############################################################################### +# Extension for Mifare reader enable +MIFARE_READER_ENABLE=0x01 + +############################################################################### +# Firmware file type +#.so file 0x01 +#.bin file 0x02 +NXP_FW_TYPE=0x01 + +############################################################################### +# System clock source selection configuration +#define CLK_SRC_XTAL 1 +#define CLK_SRC_PLL 2 +NXP_SYS_CLK_SRC_SEL=0x01 + +############################################################################### +# Dynamic RSSI feature enable +# Disable 0x00 +# Enable 0x01 +NXP_AGC_DEBUG_ENABLE=0x00 + +############################################################################### +# NXP proprietary settings +NXP_ACT_PROP_EXTN={2F, 02, 00} + +############################################################################### +# NFC forum profile settings +NXP_NFC_PROFILE_EXTN={20, 02, 05, 01, A0, 44, 01, 00} + + +############################################################################### +# To enable i2c fragmentation set i2c fragmentation enable 0x01 to disable set +# to 0x00 +NXP_I2C_FRAGMENTATION_ENABLED=0x00 + +############################################################################### +# System clock frequency selection configuration +#define CLK_FREQ_13MHZ 1 +#define CLK_FREQ_19_2MHZ 2 +#define CLK_FREQ_24MHZ 3 +#define CLK_FREQ_26MHZ 4 +#define CLK_FREQ_38_4MHZ 5 +#define CLK_FREQ_52MHZ 6 +NXP_SYS_CLK_FREQ_SEL=0x02 + +############################################################################### +# The timeout value to be used for clock request acknowledgment +# min value = 0x01 to max = 0x06 +NXP_SYS_CLOCK_TO_CFG=0x06 + +############################################################################### +# TVDD configurations settings +# Allow NFCC to configure External TVDD +# There are two possible configurations (0x01 or 0x02): +# CFG1: Vbat is used to generate the VDD(TX) through TXLDO +# CFG2: external 5V is used to generate the VDD(TX) through TXLDO +NXP_EXT_TVDD_CFG=0x02 + +# CFG1: 3.3V for both Reader and Card modes +NXP_EXT_TVDD_CFG_1={20, 02, 0F, 01, A0, 0E, 0B, 31, 01, 01, 31, 00, 00, 00, 01, 00, D0, 0C} + +# CFG2: VBAT2 to 5V and 4.7V for both Reader and Card modes +NXP_EXT_TVDD_CFG_2={20, 02, 0F, 01, A0, 0E, 0B, 11, 01, C2, B2, 00, B2, 1E, 1F, 00, D0, 0C} + +############################################################################### +# Core configuration settings +NXP_CORE_CONF={ 20, 02, 31, 0F, + 85, 01, 01, + 28, 01, 00, + 21, 01, 00, + 30, 01, 08, + 31, 01, 03, + 32, 01, 60, + 38, 01, 01, + 33, 04, 01, 02, 03, 04, + 54, 01, 06, + 50, 01, 02, + 5B, 01, 00, + 80, 01, 01, + 81, 01, 01, + 82, 01, 0E, + 18, 01, 01 +} + +############################################################################### +# NXP Proprietary core configuration extensions +# For more details refer to the NFC Controller User Manual +NXP_CORE_CONF_EXTN={20, 02, 09, 02, + A0, 5E, 01, 01, + A0, 40, 01, 00 +} + +############################################################################### +# RF configuration settings +# Below settings relates to OM5578 demo kit RF performance optimization +#NXP_RF_CONF_BLK_1={ 20, 02, A3, 13, +# A0, 0D, 06, 04, 35, 90, 01, F4, 01, +# A0, 0D, 06, 06, 44, 01, 90, 03, 00, +# A0, 0D, 06, 06, 30, B0, 01, 10, 00, +# A0, 0D, 06, 06, 42, 02, 00, FF, FF, +# A0, 0D, 03, 06, 3F, 04, +# A0, 0D, 06, 20, 42, 88, 00, FF, FF, +# A0, 0D, 04, 22, 44, 22, 00, +# A0, 0D, 06, 22, 2D, 50, 34, 0C, 00, +# A0, 0D, 06, 32, 42, F8, 00, FF, FF, +# A0, 0D, 06, 34, 2D, 24, 37, 0C, 00, +# A0, 0D, 06, 34, 33, 86, 80, 00, 70, +# A0, 0D, 04, 34, 44, 22, 00, +# A0, 0D, 06, 42, 2D, 15, 45, 0D, 00, +# A0, 0D, 04, 46, 44, 22, 00, +# A0, 0D, 06, 46, 2D, 05, 59, 0E, 00, +# A0, 0D, 06, 44, 42, 88, 00, FF, FF, +# A0, 0D, 06, 56, 2D, 05, 9F, 0C, 00, +# A0, 0D, 06, 54, 42, 88, 00, FF, FF, +# A0, 0D, 06, 0A, 33, 80, 86, 00, 70 +#} + +############################################################################### +# Extended APDU length for ISO_DEP +ISO_DEP_MAX_TRANSCEIVE=0xFEFF + +############################################################################### +# Choose the presence-check algorithm for type-4 tag. If not defined, the default value is 1. +# 0 NFA_RW_PRES_CHK_DEFAULT; Let stack selects an algorithm +# 1 NFA_RW_PRES_CHK_I_BLOCK; ISO-DEP protocol's empty I-block +# 2 NFA_RW_PRES_CHK_ISO_DEP_NAK; ISO-DEP protocol's nak presence check command +PRESENCE_CHECK_ALGORITHM=2 + +############################################################################### +#T4T NFCEE ENABLE +#bit pos 0 = Enable T4T NFCEE from NFCC (Only wired R/W activated, RF read only activated) +NXP_T4T_NFCEE_ENABLE=0x01 + +############################################################################### +#Set the T4TNfcee AID Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen off unlock +# bit pos 4 = Screen On lock +# bit pos 5 = Screen Off lock +DEFAULT_T4TNFCEE_AID_POWER_STATE=0x3B + +############################################################################### diff --git a/modules/PN7160TokenProvider/main/auth_token_providerImpl.cpp b/modules/PN7160TokenProvider/main/auth_token_providerImpl.cpp new file mode 100644 index 000000000..c33a27435 --- /dev/null +++ b/modules/PN7160TokenProvider/main/auth_token_providerImpl.cpp @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "auth_token_providerImpl.hpp" +#include + +std::string rfid_to_string(char const rfid[], size_t length) { + std::stringstream ss; + + for (size_t i = 0; i < length; ++i) { + ss << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << static_cast(rfid[i]); + } + + return ss.str(); +}; + +namespace module { +namespace main { + +void auth_token_providerImpl::init() { + if (config.disable_nfc_rfid) { + return; + } + + std::filesystem::path config_path = mod->info.paths.etc / "libnfc_config"; + EVLOG_info << "Using configuration path " << config_path << " to look for 'libnfc-nci.conf' and 'libnfc-nxp.conf'"; + try { + this->nfc_handler = std::make_unique(config_path); + } catch (const std::exception& e) { + EVLOG_error << "Failed to initialize libnfc handler: " << e.what(); + } +} + +void auth_token_providerImpl::new_rfid_token_callback(char* uid, size_t length, NfcHandler::Protocol protocol) { + + // debounce + const auto now = std::chrono::steady_clock::now(); + const auto debounce_interval = std::chrono::milliseconds(config.token_debounce_interval_ms); + + if (now < this->last_rfid_submit + debounce_interval) { + // nothing to do, just debounce + return; + } + + if (uid == nullptr || length == 0 || length > 32) { + // NOTE (aw): invalid data?, can this even happen? + // NOTE (aw): we should probably log here? + return; + } + + // convert token to string and publish ist + types::authorization::ProvidedIdToken token; + + token.id_token.type = [](NfcHandler::Protocol const in) { + switch (in) { + case NfcHandler::Protocol::ISO_IEC_15693: + return types::authorization::IdTokenType::ISO15693; + case NfcHandler::Protocol::MIFARE: + return types::authorization::IdTokenType::ISO14443; + } + + // FIXME (aw): default would be unknown, what to do here? + // choosing Local here, although this is not the proper way + return types::authorization::IdTokenType::Local; + }(protocol); + token.id_token.value = rfid_to_string(uid, length); + token.authorization_type = types::authorization::AuthorizationType::RFID; + + if (config.debug) { + EVLOG_info << "Publishing new rfid/nfc token: " << token; + } + this->publish_provided_token(token); + + this->last_rfid_submit = now; +} + +void auth_token_providerImpl::ready() { + if (this->nfc_handler) { + this->nfc_handler->start( + [this](auto&&... args) { this->new_rfid_token_callback(std::forward(args)...); }); + } +} + +} // namespace main +} // namespace module diff --git a/modules/PN7160TokenProvider/main/auth_token_providerImpl.hpp b/modules/PN7160TokenProvider/main/auth_token_providerImpl.hpp new file mode 100644 index 000000000..160b4d047 --- /dev/null +++ b/modules/PN7160TokenProvider/main/auth_token_providerImpl.hpp @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest +#ifndef MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP +#define MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP + +// +// AUTO GENERATED - MARKED REGIONS WILL BE KEPT +// template version 3 +// + +#include + +#include "../PN7160TokenProvider.hpp" + +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 +// insert your custom include headers here +#include "libnfc_handler.hpp" +// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 + +namespace module { +namespace main { + +struct Conf { + int token_debounce_interval_ms; + bool disable_nfc_rfid; + bool debug; +}; + +class auth_token_providerImpl : public auth_token_providerImplBase { +public: + auth_token_providerImpl() = delete; + auth_token_providerImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, + Conf& config) : + auth_token_providerImplBase(ev, "main"), mod(mod), config(config){}; + + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + // insert your public definitions here + // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 + +protected: + // no commands defined for this interface + + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + // insert your protected definitions here + // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 + +private: + const Everest::PtrContainer& mod; + const Conf& config; + + virtual void init() override; + virtual void ready() override; + + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 + + std::unique_ptr nfc_handler{nullptr}; + + void new_rfid_token_callback(char*, size_t, NfcHandler::Protocol); + + std::chrono::steady_clock::time_point last_rfid_submit{}; + + // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 +}; + +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 +// insert other definitions here +// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 + +} // namespace main +} // namespace module + +#endif // MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP diff --git a/modules/PN7160TokenProvider/main/libnfc_handler.cpp b/modules/PN7160TokenProvider/main/libnfc_handler.cpp new file mode 100644 index 000000000..8b00ce29f --- /dev/null +++ b/modules/PN7160TokenProvider/main/libnfc_handler.cpp @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include +#include +#include +#include + +extern "C" { +#include +#include +} + +#include "libnfc_handler.hpp" + +// NOTE (aw): access to this variable is not thread safe +// but for the current "one-shot" use, this should not be necessary +static NfcHandler* nfc_handler_instance{nullptr}; +static nfcTagCallback_t nfc_callbacks; + +NfcHandler::NfcHandler(const std::filesystem::path& config_path) { + // we could have also used a singleton instance, + if (nfc_handler_instance) { + throw std::runtime_error("Only one nfc handler instance allowed"); + } + + setConfigPath(config_path.c_str()); + + InitializeLogLevel(); + + if (doInitialize() != 0) { + throw std::runtime_error("Failed to initialize libnfc_nci library"); + } + + nfc_callbacks.onTagArrival = [](nfc_tag_info_t* tag_info) { nfc_handler_instance->on_tag_arrival(tag_info); }; + + nfc_callbacks.onTagDeparture = []() { nfc_handler_instance->on_tag_departure(); }; + + nfc_handler_instance = this; +} + +bool NfcHandler::start(Callback callback_) { + if (this->callback) { + return false; + } + + this->callback = std::move(callback_); + + registerTagCallback(&nfc_callbacks); + // enable discovery in reader-only mody, no host-routing/host-card-emulation and force a restart + // doEnableDiscovery (int technologies_mask, + // int reader_only_mode, + // int enable_host_routing, + // int restart) + doEnableDiscovery(DEFAULT_NFA_TECH_MASK, 0x01, 0x0, 0x1); + + return true; +} + +void NfcHandler::on_tag_arrival(void* tag_info_) { + // unfortunately, typedefs can't be forward declared, therefor we need to do it here + const auto tag_info = reinterpret_cast(tag_info_); + + const auto protocol = [](tNFC_PROTOCOL const in) { + if (in == NFA_PROTOCOL_MIFARE) { + return Protocol::MIFARE; + } else if (in == NFA_PROTOCOL_15693) { + return Protocol::ISO_IEC_15693; + } + + return Protocol::UNKNOWN; + }(tag_info->protocol); + + if (this->callback) { + this->callback(tag_info->uid, tag_info->uid_length, protocol); + } else { + // this should not happen + // assert(false); + } +} + +void NfcHandler::on_tag_departure() { + // handle tag departure +} + +NfcHandler::~NfcHandler() { + disableDiscovery(); + deregisterTagCallback(); + doDeinitialize(); +} diff --git a/modules/PN7160TokenProvider/main/libnfc_handler.hpp b/modules/PN7160TokenProvider/main/libnfc_handler.hpp new file mode 100644 index 000000000..5ab0dc20c --- /dev/null +++ b/modules/PN7160TokenProvider/main/libnfc_handler.hpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#pragma once + +#include +#include +#include +#include + +#include + +class NfcHandler { +public: + enum class Protocol { + UNKNOWN, + MIFARE, + ISO_IEC_15693, + }; + + using Callback = std::function; + + NfcHandler(const std::filesystem::path& config_path); + ~NfcHandler(); + + bool start(Callback); + +private: + void on_tag_arrival(void* pTagInfo); + void on_tag_departure(); + + Callback callback{nullptr}; +}; diff --git a/modules/PN7160TokenProvider/manifest.yaml b/modules/PN7160TokenProvider/manifest.yaml new file mode 100644 index 000000000..9d64eaeb6 --- /dev/null +++ b/modules/PN7160TokenProvider/manifest.yaml @@ -0,0 +1,28 @@ +description: PN7160 RFID/NFC token provider returning the token as soon as the tag can be read by the reader +provides: + main: + description: Implementation of PN7160 RFID/NFC token provider + interface: auth_token_provider + config: + token_debounce_interval_ms: + description: Minimal wait time in ms until next token will be published (debounce interval). + type: integer + default: 3000 + minimum: 1000 + maximum: 10000 + disable_nfc_rfid: + description: Disable NFC RFID reader + type: boolean + default: false + debug: + description: Show debug output on command line. + type: boolean + default: false +metadata: + license: https://opensource.org/licenses/Apache-2.0 + authors: + - Cornelius Claussen + - Kai-Uwe Hermann + - Thilo Molitor + - Anton Wöllert + - Christoph Burandt