diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser')
8 files changed, 1984 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.c new file mode 100644 index 0000000..71e5155 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.c @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#if NFC_T4T_APDU_ENABLED + +#include "nfc_t4t_apdu.h" +#include "sdk_macros.h" +#include "nordic_common.h" +#include "app_util.h" + +#define NRF_LOG_MODULE_NAME nfc_t4t_apdu +#if NFC_T4T_APDU_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_T4T_APDU_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_T4T_APDU_LOG_COLOR +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_T4T_APDU_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "nrf_log.h" +#endif // NFC_T4T_APDU_LOG_ENABLED + +/** + * @brief Field sizes that can be present in CAPDU. + */ +#define CLASS_TYPE_SIZE 1U +#define INSTRUCTION_TYPE_SIZE 1U +#define PARAMETER_SIZE 2U +#define LC_SHORT_FORMAT_SIZE 1U +#define LC_LONG_FORMAT_SIZE 3U +#define LE_SHORT_FORMAT_SIZE 1U +#define LE_LONG_FORMAT_SIZE 2U + +/** + * @brief Values used to encode Lc field in CAPDU. + */ +#define LC_LONG_FORMAT_TOKEN 0x00 +#define LC_LONG_FORMAT_THR 0xFF + +/** + * @brief Values used to encode Le field in CAPDU. + */ +#define LE_FIELD_ABSENT 0U +#define LE_LONG_FORMAT_THR 0x0100 +#define LE_ENCODED_VAL_256 0x00 + + +#define STATUS_SIZE 2U ///< Size of Status field contained in RAPDU. + +/** + * @brief Function for calculating size of CAPDU. + */ +__STATIC_INLINE uint16_t nfc_t4t_comm_apdu_size_calc(nfc_t4t_comm_apdu_t const * const p_cmd_apdu) +{ + uint16_t res = CLASS_TYPE_SIZE + INSTRUCTION_TYPE_SIZE + PARAMETER_SIZE; + if (p_cmd_apdu->data.p_buff != NULL) + { + if (p_cmd_apdu->data.len > LC_LONG_FORMAT_THR) + { + res += LC_LONG_FORMAT_SIZE; + } + else + { + res += LC_SHORT_FORMAT_SIZE; + } + } + res += p_cmd_apdu->data.len; + if (p_cmd_apdu->resp_len != LE_FIELD_ABSENT) + { + if (p_cmd_apdu->resp_len > LE_LONG_FORMAT_THR) + { + res += LE_LONG_FORMAT_SIZE; + } + else + { + res += LE_SHORT_FORMAT_SIZE; + } + } + return res; +} + + +/** + * @brief Function for validating arguments used by CAPDU encoding procedure. + */ +__STATIC_INLINE ret_code_t nfc_t4t_comm_apdu_args_validate(nfc_t4t_comm_apdu_t const * const p_cmd_apdu, + uint8_t * p_raw_data, + uint16_t * const p_len) +{ + if ((p_cmd_apdu == NULL) || (p_raw_data == NULL) || (p_len == NULL)) + { + return NRF_ERROR_NULL; + } + + if ((p_cmd_apdu->data.p_buff != NULL) && (p_cmd_apdu->data.len == 0)) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +ret_code_t nfc_t4t_comm_apdu_encode(nfc_t4t_comm_apdu_t const * const p_cmd_apdu, + uint8_t * p_raw_data, + uint16_t * const p_len) +{ + // Validate passed arguments. + ret_code_t err_code = nfc_t4t_comm_apdu_args_validate(p_cmd_apdu, p_raw_data, p_len); + VERIFY_SUCCESS(err_code); + + // Check if there is enough memory in the provided buffer to store described CAPDU. + uint16_t comm_apdu_len = nfc_t4t_comm_apdu_size_calc(p_cmd_apdu); + if (comm_apdu_len > *p_len) + { + return NRF_ERROR_NO_MEM; + } + *p_len = comm_apdu_len; + + // Start to encode described CAPDU in the buffer. + *p_raw_data++ = p_cmd_apdu->class_byte; + *p_raw_data++ = p_cmd_apdu->instruction; + *p_raw_data++ = MSB_16(p_cmd_apdu->parameter); + *p_raw_data++ = LSB_16(p_cmd_apdu->parameter); + + // Check if optional data field should be included. + if (p_cmd_apdu->data.p_buff != NULL) + { + if (p_cmd_apdu->data.len > LC_LONG_FORMAT_THR) // Use long data length encoding. + { + *p_raw_data++ = LC_LONG_FORMAT_TOKEN; + *p_raw_data++ = MSB_16(p_cmd_apdu->data.len); + *p_raw_data++ = LSB_16(p_cmd_apdu->data.len); + } + else // Use short data length encoding. + { + *p_raw_data++ = LSB_16(p_cmd_apdu->data.len); + } + memcpy(p_raw_data, p_cmd_apdu->data.p_buff, p_cmd_apdu->data.len); + p_raw_data += p_cmd_apdu->data.len; + } + + // Check if optional response length field present (Le) should be included. + if (p_cmd_apdu->resp_len != LE_FIELD_ABSENT) + { + if (p_cmd_apdu->resp_len > LE_LONG_FORMAT_THR) // Use long response length encoding. + { + *p_raw_data++ = MSB_16(p_cmd_apdu->resp_len); + *p_raw_data++ = LSB_16(p_cmd_apdu->resp_len); + } + else // Use short response length encoding. + { + if (p_cmd_apdu->resp_len == LE_LONG_FORMAT_THR) + { + *p_raw_data++ = LE_ENCODED_VAL_256; + } + else + { + *p_raw_data++ = LSB_16(p_cmd_apdu->resp_len); + } + } + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for validating arguments used by RAPDU decoding procedure. + */ +__STATIC_INLINE ret_code_t nfc_t4t_resp_apdu_args_validate(nfc_t4t_resp_apdu_t const * const p_resp_apdu, + uint8_t const * const p_raw_data, + uint16_t len) +{ + if ((p_resp_apdu == NULL) || (p_raw_data == NULL)) + { + return NRF_ERROR_NULL; + } + + if (len < STATUS_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + return NRF_SUCCESS; +} + + +ret_code_t nfc_t4t_resp_apdu_decode(nfc_t4t_resp_apdu_t * const p_resp_apdu, + uint8_t const * const p_raw_data, + uint16_t len) +{ + // Validate passed arguments. + ret_code_t err_code = nfc_t4t_resp_apdu_args_validate(p_resp_apdu, p_raw_data, len); + VERIFY_SUCCESS(err_code); + + nfc_t4t_resp_apdu_clear(p_resp_apdu); + if (len != STATUS_SIZE) // Optional data field is present in RAPDU. + { + p_resp_apdu->data.len = len - STATUS_SIZE; + p_resp_apdu->data.p_buff = (uint8_t *) p_raw_data; + } + p_resp_apdu->status = uint16_big_decode(p_raw_data + p_resp_apdu->data.len); + + return NRF_SUCCESS; +} + + +void nfc_t4t_resp_apdu_printout(nfc_t4t_resp_apdu_t * p_resp_apdu) +{ + NRF_LOG_INFO("R-APDU status: %4X ", p_resp_apdu->status); + if (p_resp_apdu->data.p_buff != NULL) + { + NRF_LOG_INFO("R-APDU data: "); + NRF_LOG_HEXDUMP_INFO(p_resp_apdu->data.p_buff, p_resp_apdu->data.len); + } + else + { + NRF_LOG_INFO("R-APDU no data field present."); + } +} + + +#endif // NFC_T4T_APDU_ENABLED + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.h new file mode 100644 index 0000000..0aa2f3d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/apdu/nfc_t4t_apdu.h @@ -0,0 +1,221 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NFC_T4T_APDU_H__ +#define NFC_T4T_APDU_H__ + +/**@file + * + * @defgroup nfc_t4t_apdu APDU reader/writer + * @{ + * @ingroup nfc_t4t_parser + * + * @brief APDU reader/writer for Type 4 Tag communication. + * + */ + +#include <stdint.h> +#include <string.h> +#include "sdk_errors.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CLASS_BYTE_NO_SECURE_MSG 0x00 ///< Class byte indicating no secure messaging, used in C-APDU. + +/** + * @name Parameters used when selecting instruction code in C-APDU. + * @{ + */ +#define SELECT_BY_FILE_ID 0x000C ///< Select by file identifier, first or only occurence. +#define SELECT_BY_NAME 0x0400 ///< Select by name, first or only occurence. +/** @} */ + +/** + * @name Status codes contained in R-APDU. + * @{ + */ +#define RAPDU_STATUS_CMD_COMPLETED 0x9000 ///< Command completed successfully. +#define RAPDU_STATUS_SEL_ITEM_NOT_FOUND 0x6A82 ///< Selected item has not been found. +/** @} */ + +/** + * @brief Possible instruction codes in C-APDU. + */ +typedef enum +{ + NFC_T4T_CAPDU_SELECT_INS = 0xA4, ///< Code used for selecting EF or NDEF application. + NFC_T4T_CAPDU_READ_INS = 0xB0, ///< Code used for selecting EF or NDEF application. + NFC_T4T_CAPDU_UPDATE_INS = 0xD6 ///< Code used for selecting EF or NDEF application. +} nfc_t4t_comm_apdu_ins_type_t; + +/** + * @brief APDU data field descriptor. + */ +typedef struct +{ + uint16_t len; ///< Data field length. + uint8_t * p_buff; ///< Pointer to data field. +} nfc_t4t_apdu_data_t; + +/** + * @brief Command Application Protocol Data Unit (C-APDU) descriptor. + */ +typedef struct +{ + uint8_t class_byte; ///< Class byte. + nfc_t4t_comm_apdu_ins_type_t instruction; ///< The chosen code of instruction. + uint16_t parameter; ///< Parameters associated with the instruction code. + nfc_t4t_apdu_data_t data; ///< Optional data fields (Lc + data bytes). + uint16_t resp_len; ///< Optional response length field (Le). +} nfc_t4t_comm_apdu_t; + +/** + * @brief Response Application Protocol Data Unit (R-APDU) descriptor. + */ +typedef struct +{ + uint16_t status; ///< Mandatory status field. + nfc_t4t_apdu_data_t data; ///< Optional data field. +} nfc_t4t_resp_apdu_t; + +/** + * @brief Macro for verifying R-APDU descriptor status. + * + * This macro verifies R-APDU descriptor status. It will cause the exterior + * function to return nrf_error translated from R-APDU status, if the status is + * not equal to @ref RAPDU_STATUS_CMD_COMPLETED. + * + * @param[in] P_RAPDU Pointer to R-APDU descriptor. + * + * @retval NRF_ERROR_NOT_FOUND If C-APDU select command could not find the selected item. + * @retval NRF_ERROR_INTERNAL Unknown R-APDU error. + */ +#define VERIFY_RAPDU_SUCCESS(P_RAPDU) \ + if (P_RAPDU->status == RAPDU_STATUS_SEL_ITEM_NOT_FOUND) \ + { \ + return NRF_ERROR_NOT_FOUND; \ + } \ + if (P_RAPDU->status != RAPDU_STATUS_CMD_COMPLETED) \ + { \ + return NRF_ERROR_INTERNAL; \ + } + +/** + * @brief Function for clearing C-APDU descriptor and restoring its default values. + * + * @param[in] p_cmd_apdu Pointer to C-APDU descriptor. + */ +__STATIC_INLINE void nfc_t4t_comm_apdu_clear(nfc_t4t_comm_apdu_t * const p_cmd_apdu); + +/** + * @brief Function for clearing R-APDU descriptor and restoring its default values. + * + * @param[in] p_resp_apdu Pointer to R-APDU descriptor. + */ +__STATIC_INLINE void nfc_t4t_resp_apdu_clear(nfc_t4t_resp_apdu_t * const p_resp_apdu); + +/** + * @brief Function for encoding C-APDU. + * + * This function encodes C-APDU according to the provided descriptor. + * + * @param[in] p_cmd_apdu Pointer to the C-APDU descriptor. + * @param[out] p_raw_data Pointer to the buffer with encoded C-APDU. + * @param[in,out] p_len Size of the available memory for the C-APDU as input. + * Size of the generated C-APDU as output. + * + * @retval NRF_SUCCESS If C-APDU was encoded successfully. + * @retval NRF_ERROR_NO_MEM If the predicted C-APDU size is bigger than the provided buffer space. + * @retval NRF_ERROR_INVALID_PARAM If C-APDU descriptor is invalid. + * @retval NRF_ERROR_NULL If any passed argument is NULL. + */ +ret_code_t nfc_t4t_comm_apdu_encode(nfc_t4t_comm_apdu_t const * const p_cmd_apdu, + uint8_t * p_raw_data, + uint16_t * const p_len); + +/** + * @brief Function for decoding R-APDU. + * + * This function decodes buffer with encoded R-APDU and stores results in the R-APDU descriptor. + * + * @param[out] p_resp_apdu Pointer to the R-APDU descriptor. + * @param[in] p_raw_data Pointer to the buffer with encoded R-APDU. + * @param[in] len Size of of the buffer with encoded R-APDU. + * + * @retval NRF_SUCCESS If R-APDU was encoded successfully. + * @retval NRF_ERROR_INVALID_LENGTH If the buffer is too small to hold a valid R-APDU. + * @retval NRF_ERROR_NULL If any passed argument is NULL. + */ +ret_code_t nfc_t4t_resp_apdu_decode(nfc_t4t_resp_apdu_t * const p_resp_apdu, + uint8_t const * const p_raw_data, + uint16_t len); + +/** + * @brief Function for printing a R-APDU descriptor. + * + * This function prints a R-APDU descriptor. + * + * @param[in] p_resp_apdu Pointer to the R-APDU descriptor. + */ +void nfc_t4t_resp_apdu_printout(nfc_t4t_resp_apdu_t * p_resp_apdu); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nfc_t4t_comm_apdu_clear(nfc_t4t_comm_apdu_t * const p_cmd_apdu) +{ + memset(p_cmd_apdu, 0, sizeof(nfc_t4t_comm_apdu_t)); +} + +__STATIC_INLINE void nfc_t4t_resp_apdu_clear(nfc_t4t_resp_apdu_t * const p_resp_apdu) +{ + memset(p_resp_apdu, 0, sizeof(nfc_t4t_resp_apdu_t)); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_T4T_APDU_H__ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.c new file mode 100644 index 0000000..197e0a0 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.c @@ -0,0 +1,266 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#if NFC_T4T_CC_FILE_PARSER_ENABLED + +#include <string.h> +#include "nfc_t4t_cc_file.h" +#include "sdk_macros.h" +#include "nordic_common.h" +#include "app_util.h" + +#define NRF_LOG_MODULE_NAME nfc_t4t_cc_file_parser +#if NFC_T4T_CC_FILE_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_T4T_CC_FILE_PARSER_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_T4T_CC_FILE_PARSER_INFO_COLOR +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "nrf_log.h" +#endif // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED + +/** + * @brief Valid value range for CCLEN field. + */ +#define CC_LEN_MIN_VALUE 0x000F +#define CC_LEN_MAX_VALUE 0xFFFE + +/** + * @brief Valid major versions of Type 4 Tag specification. + */ +#define NFC_T4T_EXTENDED_MAJOR_VER 0x03 ///< Major version number allowing first TLV block to be Extended NDEF File Control TLV +#define NFC_T4T_REGULAR_MAJOR_VER 0x02 ///< Major version number allowing first TLV block to be NDEF File Control TLV + +/** + * @brief Valid value range for MLe field. + */ +#define MLE_LEN_MIN_VALUE 0x000F +#define MLE_LEN_MAX_VALUE 0xFFFF + +/** + * @brief Valid value range for MLc field. + */ +#define MLC_LEN_MIN_VALUE 0x0001 +#define MLC_LEN_MAX_VALUE 0xFFFF + +/** + * @brief Field sizes that are present in CC file. + */ +#define CC_LEN_FIELD_SIZE 2U +#define MAP_VER_FIELD_SIZE 1U +#define MLE_FIELD_SIZE 2U +#define MLC_FIELD_SIZE 2U + +/// Gets least significant nibble (a 4-bit value) from a byte. +#define LSN_GET(val) (val & 0x0F) + +/// Gets most significant nibble (a 4-bit value) from a byte. +#define MSN_GET(val) ((val >> 4) & 0x0F) + +/** + * @brief Function for validating arguments used by CC file parsing procedure. + */ +__STATIC_INLINE ret_code_t nfc_t4t_cc_args_validate(nfc_t4t_capability_container_t * p_t4t_cc_file, + uint8_t * p_raw_data, + uint16_t len) +{ + if ( (p_t4t_cc_file == NULL) + || (p_t4t_cc_file->p_tlv_block_array == NULL) + || (p_raw_data == NULL) ) + { + return NRF_ERROR_NULL; + } + + if ( (len < CC_LEN_MIN_VALUE) || (len > CC_LEN_MAX_VALUE) ) + { + return NRF_ERROR_INVALID_LENGTH; + } + + if (p_t4t_cc_file->max_tlv_blocks == 0) + { + return NRF_ERROR_NO_MEM; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for validating CC file descriptor content. + */ +__STATIC_INLINE ret_code_t nfc_t4t_cc_file_validate(nfc_t4t_capability_container_t * p_t4t_cc_file) +{ + uint16_t type = p_t4t_cc_file->p_tlv_block_array[0].type; + + if ( (p_t4t_cc_file->major_version == NFC_T4T_EXTENDED_MAJOR_VER + && type == EXTENDED_NDEF_FILE_CONTROL_TLV) || + (p_t4t_cc_file->major_version == NFC_T4T_REGULAR_MAJOR_VER + && type == NDEF_FILE_CONTROL_TLV) ) + { + return NRF_SUCCESS; + } + + return NRF_ERROR_INVALID_DATA; +} + + +/** + * @brief Function for clearing all TLV blocks from CC file descriptor. + */ +__STATIC_INLINE void nfc_t4t_cc_file_clear(nfc_t4t_capability_container_t * p_t4t_cc_file) +{ + p_t4t_cc_file->tlv_count = 0; +} + + +/** + * @brief Function for adding a TLV block to the CC file descriptor. + */ +static ret_code_t nfc_t4t_tlv_block_insert(nfc_t4t_capability_container_t * p_t4t_cc_file, + nfc_t4t_tlv_block_t * p_tlv_block) +{ + if (p_t4t_cc_file->tlv_count == p_t4t_cc_file->max_tlv_blocks) + { + return NRF_ERROR_NO_MEM; + } + + // Copy contents of the source block. + p_t4t_cc_file->p_tlv_block_array[p_t4t_cc_file->tlv_count] = *p_tlv_block; + p_t4t_cc_file->tlv_count++; + + return NRF_SUCCESS; +} + + +ret_code_t nfc_t4t_cc_file_parse(nfc_t4t_capability_container_t * p_t4t_cc_file, + uint8_t * p_raw_data, + uint16_t len) +{ + ret_code_t err_code = nfc_t4t_cc_args_validate(p_t4t_cc_file, p_raw_data, len); + VERIFY_SUCCESS(err_code); + + uint8_t * p_offset = p_raw_data; + nfc_t4t_cc_file_clear(p_t4t_cc_file); + + p_t4t_cc_file->len = uint16_big_decode(p_offset); + p_offset += CC_LEN_FIELD_SIZE; + + p_t4t_cc_file->major_version = MSN_GET(*p_offset); + p_t4t_cc_file->minor_version = LSN_GET(*p_offset); + p_offset += MAP_VER_FIELD_SIZE; + + p_t4t_cc_file->max_rapdu_size = uint16_big_decode(p_offset); + p_offset += MLE_FIELD_SIZE; + + p_t4t_cc_file->max_capdu_size = uint16_big_decode(p_offset); + p_offset += MLC_FIELD_SIZE; + + nfc_t4t_tlv_block_t new_block; + len -= (p_offset - p_raw_data); + while (len > 0) + { + uint16_t tlv_len = len; + err_code = nfc_t4t_file_control_tlv_parse(&new_block, p_offset, &tlv_len); + VERIFY_SUCCESS(err_code); + p_offset += tlv_len; + len -= tlv_len; + + err_code = nfc_t4t_tlv_block_insert(p_t4t_cc_file, &new_block); + VERIFY_SUCCESS(err_code); + } + + return nfc_t4t_cc_file_validate(p_t4t_cc_file); +} + + +nfc_t4t_tlv_block_t * nfc_t4t_file_content_get(nfc_t4t_capability_container_t * p_t4t_cc_file, + uint16_t file_id) +{ + nfc_t4t_tlv_block_t * p_tlv_array = p_t4t_cc_file->p_tlv_block_array; + for (uint8_t i = 0; i < p_t4t_cc_file->tlv_count; i++) + { + nfc_t4t_file_control_val_t * p_tlv_value = &p_tlv_array[i].value; + if (p_tlv_value->file_id == file_id) + { + return (p_tlv_array + i); + } + } + return NULL; +} + + +ret_code_t nfc_t4t_file_content_set(nfc_t4t_capability_container_t * p_t4t_cc_file, + nfc_t4t_file_t file, + uint16_t file_id) +{ + nfc_t4t_tlv_block_t * p_tlv_block; + + p_tlv_block = nfc_t4t_file_content_get(p_t4t_cc_file, file_id); + if (p_tlv_block != NULL) + { + p_tlv_block->value.file = file; + return NRF_SUCCESS; + } + return NRF_ERROR_NOT_FOUND; +} + + +void nfc_t4t_cc_file_printout(nfc_t4t_capability_container_t * p_t4t_cc_file) +{ + NRF_LOG_INFO("Capability Container File content: ") + NRF_LOG_INFO("CCLEN: %d ", p_t4t_cc_file->len); + NRF_LOG_INFO("Mapping Version: %d.%d ", + p_t4t_cc_file->major_version, + p_t4t_cc_file->minor_version); + NRF_LOG_INFO("MLe: %d ", p_t4t_cc_file->max_rapdu_size) + NRF_LOG_INFO("MLc: %d ", p_t4t_cc_file->max_capdu_size) + + NRF_LOG_INFO("Capability Container File contains %d File Control TLV block(s).", + p_t4t_cc_file->tlv_count); + for (uint8_t i = 0; i < p_t4t_cc_file->tlv_count; i++) + { + nfc_t4t_file_control_tlv_printout(i, &p_t4t_cc_file->p_tlv_block_array[i]); + } +} + + +#endif // NFC_T4T_CC_FILE_PARSER_ENABLED + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.h new file mode 100644 index 0000000..dc41c2c --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.h @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NFC_T4T_CC_FILE_H__ +#define NFC_T4T_CC_FILE_H__ + +/**@file + * + * @defgroup nfc_t4t_cc_file CC file parser + * @{ + * @ingroup nfc_t4t_parser + * + * @brief Capability Container file parser for Type 4 Tag. + * + */ + +#include <stdint.h> +#include "sdk_errors.h" +#include "nfc_t4t_tlv_block.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Descriptor for the Capability Container (CC) file of Type 4 Tag. + */ +typedef struct +{ + nfc_t4t_tlv_block_t * p_tlv_block_array; ///< Pointer to the array for TLV blocks. + uint16_t tlv_count; ///< Number of TLV blocks stored in the Type 4 Tag. + uint16_t const max_tlv_blocks; ///< Maximum number of TLV blocks. + uint16_t len; ///< Size (bytes) of a Capability Container including this field. + uint16_t max_rapdu_size; ///< MLe field - maximum R-APDU data size (bytes). + uint16_t max_capdu_size; ///< MLc field - maximum C-APDU data size (bytes). + uint8_t major_version; ///< Major version of the supported Type 4 Tag specification. + uint8_t minor_version; ///< Minor version of the supported Type 4 Tag specification. +} nfc_t4t_capability_container_t; + +/** + * @brief Macro for creating and initializing a Type 4 Tag Capability Container descriptor. + * + * This macro creates and initializes a static instance of a @ref nfc_t4t_capability_container_t + * structure and an array of @ref nfc_t4t_tlv_block_t descriptors. + * + * Use the macro @ref NFC_T4T_CC_DESC to access the Type 4 Tag descriptor instance. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] MAX_BLOCKS Maximum number of @ref nfc_t4t_tlv_block_t descriptors that can be + * stored in the array. + * + */ +#define NFC_T4T_CC_DESC_DEF(NAME, MAX_BLOCKS) \ + static nfc_t4t_tlv_block_t NAME##_tlv_block_array[MAX_BLOCKS]; \ + static nfc_t4t_capability_container_t NAME##_type_4_tag = \ + { \ + .max_tlv_blocks = MAX_BLOCKS, \ + .p_tlv_block_array = NAME##_tlv_block_array, \ + .tlv_count = 0 \ + } + +/** + * @brief Macro for accessing the @ref nfc_t4t_capability_container_t instance that was created + * with @ref NFC_T4T_CC_DESC_DEF. + * + * @param[in] NAME Name of the created descriptor instance. + */ +#define NFC_T4T_CC_DESC(NAME) (NAME##_type_4_tag) + +/** + * @brief Function for parsing raw data of a CC file, read from a Type 4 Tag. + * + * This function parses raw data of a Capability Container file and stores the results in its + * descriptor. + * + * @param[in,out] p_t4t_cc_file Pointer to the CC file descriptor that will be filled with + * parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw data. + * @param[in] len Buffer length. + * + * @retval NRF_SUCCESS If operation was successful. + * @retval NRF_ERROR_NULL If any of the provided pointer arguments is NULL. + * @retval NRF_ERROR_INVALID_LENGTH If provided buffer exceeds a valid CC file length range. + * @retval NRF_ERROR_INVALID_DATA If mapping version of Type 4 Tag specification is not a + * compatible CC file structure. + * @retval Other Other error codes might be returned depending on + * @ref nfc_t4t_file_control_tlv_parse function. + */ +ret_code_t nfc_t4t_cc_file_parse(nfc_t4t_capability_container_t * p_t4t_cc_file, + uint8_t * p_raw_data, + uint16_t len); + +/** + * @brief Function for finding File Control TLV block within the CC file descriptor. + * + * This function finds File Control TLV block that matches + * the specified file ID within the CC file descriptor. + * + * @param[in] p_t4t_cc_file Pointer to the CC file descriptor. + * @param[in] file_id File identifier. + * + * @retval TLV Pointer to the File Control TLV. + * @retval NULL If TLV with the specified File ID was not found. + */ +nfc_t4t_tlv_block_t * nfc_t4t_file_content_get(nfc_t4t_capability_container_t * p_t4t_cc_file, + uint16_t file_id); + +/** + * @brief Function for binding a file with its File Control TLV block. + * + * This function binds file content with its File Control TLV block, in which + * maximal file size and access conditions are stored. + * + * @param[in,out] p_t4t_cc_file Pointer to the CC file descriptor. + * @param[in] file File descriptor. + * @param[in] file_id File identifier. + * + * @retval NRF_SUCCESS If operation was successful. + * @retval NRF_ERROR_NOT_FOUND If the provided file ID does not match any ID stored in TLV blocks + * of the CC file. + */ +ret_code_t nfc_t4t_file_content_set(nfc_t4t_capability_container_t * p_t4t_cc_file, + nfc_t4t_file_t file, + uint16_t file_id); + +/** + * @brief Function for printing the CC file descriptor. + * + * This function prints the CC file descriptor. + * + * @param[in] p_t4t_cc_file Pointer to the CC file. + */ +void nfc_t4t_cc_file_printout(nfc_t4t_capability_container_t * p_t4t_cc_file); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_T4T_CC_FILE_H__ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.c new file mode 100644 index 0000000..f27625f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.c @@ -0,0 +1,401 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#if NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED + +#include "nfc_t4t_hl_detection_procedures.h" +#include "nfc_t4t_apdu.h" +#include "adafruit_pn532.h" +#include "sdk_macros.h" +#include "nordic_common.h" + +#define NRF_LOG_MODULE_NAME nfc_t4t_hl_detection_procedures +#if NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_T4T_HL_DETECTION_PROCEDURES_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_T4T_HL_DETECTION_PROCEDURES_INFO_COLOR +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "nrf_log.h" +#endif // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED + +#define CC_FILE_ID 0xE103 ///< File Identifier of Capability Container. +#define FILE_ID_SIZE 2 ///< Size of File Identifier field in CC file. +#define MIN_MAX_RAPDU_SIZE 0x0F ///< Minimal value of maximal RAPDU data field size. +#define NDEF_FILE_NLEN_FIELD_SIZE 2 ///< Size of NLEN field in NDEF file. +#define NDEF_APP_PROC_RESP_LEN 256 ///< Maximal size of RAPDU data in the NDEF Tag Application Select Procedure. + +// Adafruit library limitations. +#define MAX_ADAFRUIT_RAPDU_SIZE 242 ///< Maximal value of RAPDU data field size +#define MAX_ADAFRUIT_CAPDU_SIZE 240 ///< Maximal value of CAPDU data field size + +static uint8_t m_file_id[FILE_ID_SIZE]; ///< Buffer for selected EF ID storage. +static const uint8_t m_nfc_t4t_select_ndef_app_data[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}; ///< NDEF Tag Application name. +static const uint8_t m_nlen_update_value[] = {0x00, 0x00}; ///< NLEN value used in NDEF Update Procedure. + +/** + * @brief Function for performing APDU exchanges with Adafruit library. + */ +static ret_code_t nfc_t4t_apdu_exchange(nfc_t4t_comm_apdu_t * const p_capdu, + nfc_t4t_resp_apdu_t * const p_rapdu, + uint8_t * const p_apdu_buff, + uint8_t resp_len) +{ + if (resp_len > APDU_BUFF_SIZE) + { + return NRF_ERROR_NO_MEM; + } + + uint16_t apdu_buff_len = APDU_BUFF_SIZE; + ret_code_t err_code = nfc_t4t_comm_apdu_encode(p_capdu, + p_apdu_buff, + &apdu_buff_len); + VERIFY_SUCCESS(err_code); + + err_code = adafruit_pn532_in_data_exchange(p_apdu_buff, apdu_buff_len, p_apdu_buff, &resp_len); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_resp_apdu_decode(p_rapdu, p_apdu_buff, resp_len); + VERIFY_SUCCESS(err_code); + + nfc_t4t_resp_apdu_printout(p_rapdu); + VERIFY_RAPDU_SUCCESS(p_rapdu); + + return err_code; +} + +/** + * @brief Function for performing APDU exchanges with Adafruit library with default response length. + */ +static ret_code_t nfc_t4t_apdu_default_exchange(nfc_t4t_comm_apdu_t * const p_capdu, + nfc_t4t_resp_apdu_t * const p_rapdu, + uint8_t * const p_apdu_buff) +{ + if (p_capdu->resp_len + sizeof(p_rapdu->status) > UINT8_MAX) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t resp_len = (uint8_t) (p_capdu->resp_len + sizeof(p_rapdu->status)); + ret_code_t err_code = nfc_t4t_apdu_exchange(p_capdu, p_rapdu, p_apdu_buff, resp_len); + + return err_code; +} + + +/** + * @brief Function for saving part of EF (contained in RAPDU) in storage buffer. + */ +static ret_code_t nfc_t4t_file_chunk_save(nfc_t4t_resp_apdu_t const * const p_rapdu, + uint8_t * const p_storage_buff, + uint16_t storage_buff_len, + uint16_t * const p_file_offset) +{ + if (p_rapdu->data.p_buff == NULL) + { + return NRF_ERROR_NULL; + } + if ((*p_file_offset) + p_rapdu->data.len > storage_buff_len) + { + return NRF_ERROR_NO_MEM; + } + + memcpy(p_storage_buff + (*p_file_offset), p_rapdu->data.p_buff, p_rapdu->data.len); + *p_file_offset += p_rapdu->data.len; + + return NRF_SUCCESS; +} + + +/** + * @brief Function for updating the remaining length of the read file. + */ +static ret_code_t nfc_t4t_file_len_update(nfc_t4t_resp_apdu_t const * const p_rapdu, + uint16_t * const p_len) +{ + if (*p_len < p_rapdu->data.len) + { + return NRF_ERROR_INVALID_DATA; + } + *p_len -= p_rapdu->data.len; + + return NRF_SUCCESS; +} + + +ret_code_t nfc_t4t_ndef_tag_app_select(void) +{ + ret_code_t err_code; + nfc_t4t_comm_apdu_t capdu; + nfc_t4t_resp_apdu_t rapdu; + uint8_t apdu_buff[APDU_BUFF_SIZE]; + + NRF_LOG_INFO("NDEF Tag Application Select Procedure "); + + nfc_t4t_comm_apdu_clear(&capdu); + capdu.instruction = NFC_T4T_CAPDU_SELECT_INS; + capdu.parameter = SELECT_BY_NAME; + capdu.data.p_buff = (uint8_t *) m_nfc_t4t_select_ndef_app_data; + capdu.data.len = sizeof(m_nfc_t4t_select_ndef_app_data); + capdu.resp_len = NDEF_APP_PROC_RESP_LEN; + + err_code = nfc_t4t_apdu_exchange(&capdu, &rapdu, apdu_buff, sizeof(rapdu.status)); + NRF_LOG_RAW_INFO("\r\n"); + return err_code; +} + + +ret_code_t nfc_t4t_file_select(uint16_t file_id) +{ + ret_code_t err_code; + nfc_t4t_comm_apdu_t capdu; + nfc_t4t_resp_apdu_t rapdu; + uint8_t apdu_buff[APDU_BUFF_SIZE]; + + if (file_id != CC_FILE_ID) + { + NRF_LOG_INFO("File (ID = %4X) Select Procedure ", file_id); + } + UNUSED_RETURN_VALUE(uint16_big_encode(file_id, m_file_id)); + + nfc_t4t_comm_apdu_clear(&capdu); + capdu.instruction = NFC_T4T_CAPDU_SELECT_INS; + capdu.parameter = SELECT_BY_FILE_ID; + capdu.data.p_buff = m_file_id; + capdu.data.len = sizeof(m_file_id); + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + NRF_LOG_RAW_INFO("\r\n"); + return err_code; +} + + +ret_code_t nfc_t4t_cc_select(void) +{ + NRF_LOG_INFO("Capability Container Select Procedure "); + + return nfc_t4t_file_select(CC_FILE_ID); +} + + +ret_code_t nfc_t4t_cc_read(nfc_t4t_capability_container_t * const p_cc_file) +{ + ret_code_t err_code; + nfc_t4t_comm_apdu_t capdu; + nfc_t4t_resp_apdu_t rapdu; + uint16_t clen; + uint16_t file_offset = 0; + uint8_t storage_buff[CC_STORAGE_BUFF_SIZE]; + uint8_t apdu_buff[APDU_BUFF_SIZE]; + + NRF_LOG_INFO("Capability Container Read Procedure "); + + nfc_t4t_comm_apdu_clear(&capdu); + capdu.instruction = NFC_T4T_CAPDU_READ_INS; + capdu.parameter = file_offset; + capdu.resp_len = MIN_MAX_RAPDU_SIZE; + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_chunk_save(&rapdu, storage_buff, CC_STORAGE_BUFF_SIZE, &file_offset); + VERIFY_SUCCESS(err_code); + + clen = uint16_big_decode(storage_buff); + err_code = nfc_t4t_file_len_update(&rapdu, &clen); + VERIFY_SUCCESS(err_code); + + while (clen > 0) + { + capdu.parameter = file_offset; + capdu.resp_len = MIN(MIN_MAX_RAPDU_SIZE, MIN(clen, MAX_ADAFRUIT_RAPDU_SIZE)); + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_chunk_save(&rapdu, storage_buff, CC_STORAGE_BUFF_SIZE, &file_offset); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_len_update(&rapdu, &clen); + VERIFY_SUCCESS(err_code); + } + + err_code = nfc_t4t_cc_file_parse(p_cc_file, storage_buff, file_offset); + + NRF_LOG_RAW_INFO("\r\n"); + return err_code; +} + + +ret_code_t nfc_t4t_ndef_read(nfc_t4t_capability_container_t * const p_cc_file, + uint8_t * p_ndef_file_buff, + uint8_t ndef_file_buff_len) +{ + ret_code_t err_code; + nfc_t4t_comm_apdu_t capdu; + nfc_t4t_resp_apdu_t rapdu; + uint16_t len; + uint16_t file_offset = 0; + uint8_t apdu_buff[APDU_BUFF_SIZE]; + + NRF_LOG_INFO("NDEF Read Procedure "); + + // Read the NLEN (NDEF length) field of NDEF file. + nfc_t4t_comm_apdu_clear(&capdu); + capdu.instruction = NFC_T4T_CAPDU_READ_INS; + capdu.parameter = file_offset; + capdu.resp_len = NDEF_FILE_NLEN_FIELD_SIZE; + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_chunk_save(&rapdu, p_ndef_file_buff, ndef_file_buff_len, &file_offset); + VERIFY_SUCCESS(err_code); + + len = uint16_big_decode(p_ndef_file_buff) + NDEF_FILE_NLEN_FIELD_SIZE; + err_code = nfc_t4t_file_len_update(&rapdu, &len); + VERIFY_SUCCESS(err_code); + + // Read the NDEF message. + while (len > 0) + { + capdu.parameter = file_offset; + capdu.resp_len = MIN(len, MIN(p_cc_file->max_rapdu_size, MAX_ADAFRUIT_RAPDU_SIZE)); + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_chunk_save(&rapdu, p_ndef_file_buff, ndef_file_buff_len, &file_offset); + VERIFY_SUCCESS(err_code); + + err_code = nfc_t4t_file_len_update(&rapdu, &len); + VERIFY_SUCCESS(err_code); + } + + // Bind NDEF File Control TLV with NDEF file. + nfc_t4t_file_t file = + { + .p_content = p_ndef_file_buff, + .len = file_offset + }; + uint16_t file_id = uint16_big_decode(m_file_id); + err_code = nfc_t4t_file_content_set(p_cc_file, file, file_id); + + NRF_LOG_RAW_INFO("\r\n"); + return err_code; +} + + +ret_code_t nfc_t4t_ndef_update(nfc_t4t_capability_container_t * const p_cc_file, + uint8_t * p_ndef_file_buff, + uint8_t ndef_file_buff_len) +{ + ret_code_t err_code; + nfc_t4t_comm_apdu_t capdu; + nfc_t4t_resp_apdu_t rapdu; + uint16_t len; + uint16_t file_offset = 0; + uint16_t file_id = uint16_big_decode(m_file_id); + uint8_t apdu_buff[APDU_BUFF_SIZE]; + nfc_t4t_tlv_block_t * p_tlv_block; + + NRF_LOG_INFO("NDEF Update Procedure "); + + if (ndef_file_buff_len < NDEF_FILE_NLEN_FIELD_SIZE) + { + return NRF_ERROR_INVALID_DATA; + } + + // Check if selected NDEF file is registered in CC file descriptor. + p_tlv_block = nfc_t4t_file_content_get(p_cc_file, file_id); + if (p_tlv_block == NULL) + { + return NRF_ERROR_NULL; + } + + // Check NDEF file capacity before writing anything to it. + len = uint16_big_decode(p_ndef_file_buff); + if ((len + NDEF_FILE_NLEN_FIELD_SIZE != ndef_file_buff_len) || + (ndef_file_buff_len > p_tlv_block->value.max_file_size)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + // Write the value 0000h in the NLEN field. + nfc_t4t_comm_apdu_clear(&capdu); + capdu.instruction = NFC_T4T_CAPDU_UPDATE_INS; + capdu.parameter = file_offset; + capdu.data.p_buff = (uint8_t *) m_nlen_update_value; + capdu.data.len = NDEF_FILE_NLEN_FIELD_SIZE; + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + file_offset += NDEF_FILE_NLEN_FIELD_SIZE; + + // Write the NDEF message in the NDEF message field. + while (len > 0) + { + capdu.parameter = file_offset; + capdu.data.p_buff = p_ndef_file_buff + file_offset; + capdu.data.len = MIN(len, MIN(p_cc_file->max_capdu_size, MAX_ADAFRUIT_CAPDU_SIZE)); + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + file_offset += capdu.data.len; + len -= capdu.data.len; + } + + // Write the length of the NDEF message in the NLEN field. + capdu.parameter = 0; + capdu.data.p_buff = p_ndef_file_buff; + capdu.data.len = NDEF_FILE_NLEN_FIELD_SIZE; + + err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff); + VERIFY_SUCCESS(err_code); + + NRF_LOG_RAW_INFO("\r\n"); + return NRF_SUCCESS; +} + + +#endif // NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.h new file mode 100644 index 0000000..7ebc56e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/hl_detection_procedure/nfc_t4t_hl_detection_procedures.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NFC_T4T_HL_DETECTION_PROCEDURES_H__ +#define NFC_T4T_HL_DETECTION_PROCEDURES_H__ + +/**@file + * + * @defgroup nfc_t4t_parser NFC Type 4 Tag parser + * @ingroup nfc_t4t + * @brief Parser for Type 4 Tag data. + * + * @defgroup nfc_t4t_hl_detection_procedures High-level NDEF Detection Procedure + * @{ + * @ingroup nfc_t4t_parser + * + * @brief High-level NDEF Detection Procedure for Type 4 Tag communication. + * + */ + +#include <stdint.h> +#include "sdk_errors.h" +#include "nfc_t4t_cc_file.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for performing NDEF Tag Application Select Procedure. + * + * This function performs NDEF Tag Application Select Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.2. + * + * @retval NRF_SUCCESS If NDEF Tag Application was successfully selected. + * @retval NRF_ERROR_NOT_FOUND If NDEF Tag Application was not found. + * @retval NRF_ERROR_NO_MEM If the APDU buffer is too small. + * @retval Other Other error codes may be returned depending on function + * @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu + * module functions. + */ +ret_code_t nfc_t4t_ndef_tag_app_select(void); + +/** + * @brief Function for performing Capability Container Select Procedure. + * + * This function performs Capability Container Select Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.3. + * + * @retval NRF_SUCCESS If the Capability Container file was successfully selected. + * @retval NRF_ERROR_NOT_FOUND If the Capability Container file was not found. + * @retval NRF_ERROR_NO_MEM If the APDU buffer is too small. + * @retval Other Other error codes might be returned depending on function + * @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu + * module functions. + */ +ret_code_t nfc_t4t_cc_select(void); + +/** + * @brief Function for performing Capability Container Read Procedure. + * + * This function performs Capability Container Read Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.4. + * + * @param[out] p_cc_file Pointer to the Capability Container descriptor. + * + * @retval NRF_SUCCESS If Capability Container file was successfully read. + * @retval NRF_ERROR_NO_MEM If APDU buffer or CC file storage buffer is too small. + * @retval NRF_ERROR_NOT_SUPPORTED If the requested response length in C-APDU is too big. + * @retval NRF_ERROR_NULL If R-APDU did not return any data bytes. + * @retval NRF_ERROR_INVALID_DATA If CCLEN field is not coherent with R-APDU data length. + * @retval Other Other error codes may be returned depending on functions + * @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_cc_file_parse, + * and on @ref nfc_t4t_apdu module functions. + */ +ret_code_t nfc_t4t_cc_read(nfc_t4t_capability_container_t * const p_cc_file); + +/** + * @brief Function for performing NDEF Select Procedure. + * + * This function performs NDEF Select Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.5. + * + * @param[in] file_id File Identifier to choose the correct file. + * + * @retval NRF_SUCCESS If NDEF file was successfully selected. + * @retval NRF_ERROR_NOT_FOUND If NDEF file was not found. + * @retval NRF_ERROR_NO_MEM If APDU buffer is too small. + * @retval Other Other error codes may be returned depending on function + * @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu + * module functions. + */ +ret_code_t nfc_t4t_file_select(uint16_t file_id); + +/** + * @brief Function for performing NDEF Read Procedure. + * + * This function performs NDEF Read Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.6. + * + * @param[in,out] p_cc_file Pointer to the Capability Container descriptor. + * @param[out] p_ndef_file_buff Pointer to the buffer where the NDEF file will be stored. + * @param[in] ndef_file_buff_len Length of the provided NDEF file buffer. + * + * @retval NRF_SUCCESS If NDEF file was successfully read. + * @retval NRF_ERROR_NO_MEM If APDU buffer or NDEF file buffer is too small. + * @retval NRF_ERROR_NOT_SUPPORTED If requested response length in C-APDU is too big. + * @retval NRF_ERROR_NULL If R-APDU did not return any data bytes. + * @retval NRF_ERROR_INVALID_DATA If NLEN field is not coherent with R-APDU data length. + * @retval Other Other error codes may be returned depending on function + * @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_file_content_set, + * and on @ref nfc_t4t_apdu module functions. + */ +ret_code_t nfc_t4t_ndef_read(nfc_t4t_capability_container_t * const p_cc_file, + uint8_t * p_ndef_file_buff, + uint8_t ndef_file_buff_len); + +/** + * @brief Function for performing NDEF Update Procedure. + * + * This function performs NDEF Update Procedure according to "Type 4 Tag Operation" + * (Version 3.0 published on 2014-07-30) chapter 5.5.7. + * + * @param[in] p_cc_file Pointer to the Capability Container descriptor. + * @param[in] p_ndef_file_buff Pointer to the buffer with NDEF file. + * @param[in] ndef_file_buff_len Length of the provided NDEF file. + * + * @retval NRF_SUCCESS If NDEF file was successfully updated. + * @retval NRF_ERROR_NO_MEM If APDU buffer or NDEF file buffer is too small. + * @retval NRF_ERROR_NOT_SUPPORTED If the requested response length in C-APDU is too big. + * @retval NRF_ERROR_INVALID_DATA If NDEF file buffer is smaller than NLEN field size. + * @retval NRF_ERROR_INVALID_LENGTH If NLEN value is not coherent with NDEF file buffer length + * or if buffer length is bigger than maximal file size. + * @retval Other Other error codes may be returned depending on function + * @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_file_content_get, + * and on @ref nfc_t4t_apdu module functions. + */ +ret_code_t nfc_t4t_ndef_update(nfc_t4t_capability_container_t * const p_cc_file, + uint8_t * p_ndef_file_buff, + uint8_t ndef_file_buff_len); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_T4T_HL_DETECTION_PROCEDURES_H__ */ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.c new file mode 100644 index 0000000..028018b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.c @@ -0,0 +1,327 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#if NFC_T4T_TLV_BLOCK_PARSER_ENABLED + +#include <string.h> +#include "nfc_t4t_tlv_block.h" +#include "app_util.h" +#include "sdk_macros.h" +#include "nordic_common.h" + +#define NRF_LOG_MODULE_NAME nfc_t4t_tlv_block_parser +#if NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "nrf_log.h" +#endif // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED + +#define TLV_TYPE_FIELD_LEN 1U ///< Length of a type field. + +/** + * @brief TLV length field related defines. + */ +#define TLV_LEN_SHORT_FIELD_LEN 1U ///< Length of a short length field. +#define TLV_LEN_LONG_FIELD_LEN 3U ///< Length of an extended length field. +#define TLV_LEN_LONG_FORMAT_TOKEN 0xFF ///< Value indicating the use of an extended length field. +#define TLV_LEN_LONG_FORMAT_TOKEN_SIZE 1U ///< Size of long format token. +#define TLV_LEN_LONG_FORMAT_MIN_VALUE 0xFF ///< The minimal value of length field that can be used in long format. + +/** + * @brief Possible sizes of TLV block. + */ +#define TLV_MIN_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_SHORT_FIELD_LEN) +#define TLV_MIN_LONG_FORMAT_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_LONG_FIELD_LEN) +#define TLV_MIN_VALUE_FIELD_SIZE 6U + +/** + * @brief Field sizes that are present in TLV block. + */ +#define FILE_CONTROL_FILE_ID_FIELD_SIZE 2U +#define FILE_CONTROL_READ_ACCESS_FIELD_SIZE 1U +#define FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE 1U +#define FILE_CONTROL_COMMON_FIELDS_SIZE (FILE_CONTROL_FILE_ID_FIELD_SIZE \ + + FILE_CONTROL_READ_ACCESS_FIELD_SIZE \ + + FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE) + +/** + * @brief Invalid values for File Identifier field. + */ +#define FILE_ID_INVALID_VALUE_0 0x0000 +#define FILE_ID_INVALID_VALUE_1 0xE102 +#define FILE_ID_INVALID_VALUE_2 0xE103 +#define FILE_ID_INVALID_VALUE_3 0x3F00 +#define FILE_ID_INVALID_VALUE_4 0x3FFF +#define FILE_ID_INVALID_VALUE_5 0xFFFF + +/** + * @brief NDEF file related defines. + */ +#define NDEF_FILE_MAX_SIZE_FIELD_SIZE 2U +#define NDEF_FILE_MAX_SIZE_MIN_VAL 0x0005 +#define NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFE +#define NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \ + + NDEF_FILE_MAX_SIZE_FIELD_SIZE) + +/** + * @brief Proprietary file related defines. + */ +#define PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE 2U +#define PROPRIETARY_FILE_MAX_SIZE_MIN_VAL 0x0003 +#define PROPRIETARY_FILE_MAX_SIZE_MAX_VAL 0xFFFE +#define PROPRIETARY_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \ + + PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE) + +/** + * @brief Extended NDEF file related defines. + */ +#define EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE 4U +#define EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL 0x0000FFFF +#define EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFFFFFE +#define EXTENDED_NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \ + + EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE) + +/** + * @brief Validates maximum file size field range. This field is present in every File Control TLV. + */ +#define NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(VALUE, MIN, MAX) \ + if ( ( (VALUE) < (MIN) ) || ( (VALUE) > (MAX) ) ) \ + { \ + return NRF_ERROR_INVALID_DATA; \ + } + + +/** + * @brief Function for validating all possible types of File Control TLV. + */ +__STATIC_INLINE ret_code_t nfc_t4t_file_control_tl_validate(nfc_t4t_tlv_block_t * p_file_control_tlv) +{ + switch (p_file_control_tlv->type) + { + case NDEF_FILE_CONTROL_TLV: + VERIFY_TRUE(p_file_control_tlv->length == NDEF_FILE_CONTROL_TLV_LEN, + NRF_ERROR_INVALID_DATA); + return NRF_SUCCESS; + + case PROPRIETARY_FILE_CONTROL_TLV: + VERIFY_TRUE(p_file_control_tlv->length == PROPRIETARY_FILE_CONTROL_TLV_LEN, + NRF_ERROR_INVALID_DATA); + return NRF_SUCCESS; + + case EXTENDED_NDEF_FILE_CONTROL_TLV: + VERIFY_TRUE(p_file_control_tlv->length == EXTENDED_NDEF_FILE_CONTROL_TLV_LEN, + NRF_ERROR_INVALID_DATA); + return NRF_SUCCESS; + + default: + return NRF_ERROR_INVALID_DATA; + } +} + + +/** + * @brief Function for parsing value field of File Control TLV. + */ +static ret_code_t nfc_t4t_file_control_value_parse(nfc_t4t_tlv_block_t * p_file_control_tlv, + uint8_t * p_value_buff) +{ + nfc_t4t_file_control_val_t * p_control_tlv_val; + + // Handle File Identifier field. + p_control_tlv_val = &p_file_control_tlv->value; + p_control_tlv_val->file_id = uint16_big_decode(p_value_buff); + p_value_buff += FILE_CONTROL_FILE_ID_FIELD_SIZE; + + switch (p_control_tlv_val->file_id) + { + case FILE_ID_INVALID_VALUE_0: + case FILE_ID_INVALID_VALUE_1: + case FILE_ID_INVALID_VALUE_2: + case FILE_ID_INVALID_VALUE_3: + case FILE_ID_INVALID_VALUE_4: + case FILE_ID_INVALID_VALUE_5: + return NRF_ERROR_INVALID_DATA; + + default: + break; + } + + // Handle Max file size field. + switch (p_file_control_tlv->type) + { + case NDEF_FILE_CONTROL_TLV: + p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff); + p_value_buff += NDEF_FILE_MAX_SIZE_FIELD_SIZE; + NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size, + NDEF_FILE_MAX_SIZE_MIN_VAL, + NDEF_FILE_MAX_SIZE_MAX_VAL); + break; + + case PROPRIETARY_FILE_CONTROL_TLV: + p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff); + p_value_buff += PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE; + NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size, + PROPRIETARY_FILE_MAX_SIZE_MIN_VAL, + PROPRIETARY_FILE_MAX_SIZE_MAX_VAL); + break; + + case EXTENDED_NDEF_FILE_CONTROL_TLV: + p_control_tlv_val->max_file_size = uint32_big_decode(p_value_buff); + p_value_buff += EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE; + NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size, + EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL, + EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL); + break; + } + + // Handle read access condition field. + p_control_tlv_val->read_access = *p_value_buff; + p_value_buff += FILE_CONTROL_READ_ACCESS_FIELD_SIZE; + + // Handle write access condition field. + p_control_tlv_val->write_access = *p_value_buff; + + return NRF_SUCCESS; +} + + +ret_code_t nfc_t4t_file_control_tlv_parse(nfc_t4t_tlv_block_t * p_file_control_tlv, + uint8_t * p_raw_data, + uint16_t * p_len) +{ + ret_code_t err_code; + uint8_t * p_offset = p_raw_data; + + if (*p_len < TLV_MIN_TL_FIELD_LEN) + { + return NRF_ERROR_INVALID_LENGTH; + } + memset(p_file_control_tlv, 0, sizeof(nfc_t4t_tlv_block_t)); + + // Handle type field of TLV block. + p_file_control_tlv->type = *p_offset; + p_offset += TLV_TYPE_FIELD_LEN; + + // Handle length field of TLV block. + if (*p_offset == TLV_LEN_LONG_FORMAT_TOKEN) + { + if (*p_len < TLV_MIN_LONG_FORMAT_TL_FIELD_LEN) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_file_control_tlv->length = uint16_big_decode(p_offset + TLV_LEN_LONG_FORMAT_TOKEN_SIZE); + p_offset += TLV_LEN_LONG_FIELD_LEN; + + if (p_file_control_tlv->length < TLV_LEN_LONG_FORMAT_MIN_VALUE) + { + return NRF_ERROR_INVALID_DATA; + } + } + else + { + p_file_control_tlv->length = *p_offset; + p_offset += TLV_LEN_SHORT_FIELD_LEN; + } + + // Calculate the total TLV block size. + uint16_t tlv_block_len = (p_offset - p_raw_data) + p_file_control_tlv->length; + if (*p_len < tlv_block_len) + { + return NRF_ERROR_INVALID_LENGTH; + } + *p_len = tlv_block_len; + + // Validate if type and length fields contain values supported by Type 4 Tag. + err_code = nfc_t4t_file_control_tl_validate(p_file_control_tlv); + VERIFY_SUCCESS(err_code); + + // Handle value field of TLV block. + err_code = nfc_t4t_file_control_value_parse(p_file_control_tlv, p_offset); + return err_code; +} + + +void nfc_t4t_file_control_tlv_printout(uint8_t num, nfc_t4t_tlv_block_t * p_t4t_tlv_block) +{ + NRF_LOG_INFO("%d file Control TLV", num); + switch (p_t4t_tlv_block->type) + { + case NDEF_FILE_CONTROL_TLV: + NRF_LOG_INFO("Type: NDEF File Control (0x%02x)", p_t4t_tlv_block->type); + break; + + case PROPRIETARY_FILE_CONTROL_TLV: + NRF_LOG_INFO("Type: Proprietary File Control (0x%02x)", p_t4t_tlv_block->type); + break; + + case EXTENDED_NDEF_FILE_CONTROL_TLV: + NRF_LOG_INFO("Type: Extended NDEF File Control (0x%02x)", p_t4t_tlv_block->type); + break; + + default: + NRF_LOG_INFO("Type: Unknown (0x%02x)", p_t4t_tlv_block->type); + } + NRF_LOG_INFO("Length (in bytes): %d", p_t4t_tlv_block->length); + + nfc_t4t_file_control_val_t * p_tlv_val = &p_t4t_tlv_block->value; + NRF_LOG_INFO("File Identifier: 0x%04X ", p_tlv_val->file_id); + NRF_LOG_INFO("Maximum file size: %d ", p_tlv_val->max_file_size); + NRF_LOG_INFO("Read access condition: 0x%02X ", p_tlv_val->read_access); + NRF_LOG_INFO("Write access condition: 0x%02x ", p_tlv_val->write_access); + + if (p_tlv_val->file.p_content != NULL) + { + NRF_LOG_INFO("NDEF file content present. Length: %d ", p_tlv_val->file.len); + NRF_LOG_HEXDUMP_INFO(p_tlv_val->file.p_content, p_tlv_val->file.len); + } + else + { + NRF_LOG_INFO("NDEF file content is not present "); + } +} + + +#endif // NFC_T4T_TLV_BLOCK_PARSER_ENABLED + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.h new file mode 100644 index 0000000..f67396b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.h @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NFC_T4T_TLV_BLOCK_H__ +#define NFC_T4T_TLV_BLOCK_H__ + +/**@file + * + * @defgroup nfc_t4t_tlv_block File Control TLV block parser for Type 4 Tag. + * @{ + * @ingroup nfc_t4t_cc_file + * + * @brief File Control TLV block parser for Type 4 Tag (T4T). + * + */ + +#include <stdint.h> +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONTROL_FILE_READ_ACCESS_GRANTED 0x00 ///< Read access granted without any security. + +/** + * @name Possible values of file write access condition field. + * @{ + */ +#define CONTROL_FILE_WRITE_ACCESS_GRANTED 0x00 ///< Write access granted without any security. +#define CONTROL_FILE_WRITE_ACCESS_DISABLED 0xFF ///< No write access granted without any security (read-only). +/** @} */ + +/** + * @brief Possible types of File Control TLV for Type 4 Tag. + */ +typedef enum +{ + NDEF_FILE_CONTROL_TLV = 0x04, ///< Control information concerning the EF file with short NDEF message. + PROPRIETARY_FILE_CONTROL_TLV = 0x05, ///< Control information concerning the Proprietary file with proprietary data. + EXTENDED_NDEF_FILE_CONTROL_TLV = 0x06 ///< Control information concerning the EF file with long NDEF message. +} nfc_t4t_tlv_block_types_t; + +/** + * @brief File content descriptor. + */ +typedef struct +{ + uint8_t * p_content; ///< Pointer to the file content. + uint16_t len; ///< Length of file content. +} nfc_t4t_file_t; + +/** + * @brief Extended NDEF/NDEF/Proprietary File Control Value descriptor. + */ +typedef struct +{ + nfc_t4t_file_t file; ///< Pointer to the described file content. + uint32_t max_file_size; ///< Maximum size (in bytes) of the file. + uint16_t file_id; ///< File identifier. + uint8_t read_access; ///< File read access condition. + uint8_t write_access; ///< File write access condition. +} nfc_t4t_file_control_val_t; + +/** + * @brief File Control TLV block descriptor. + */ +typedef struct +{ + nfc_t4t_file_control_val_t value; ///< Value field descriptor. + uint16_t length; ///< Length of the value field. + uint8_t type; ///< Type of the TLV block. +} nfc_t4t_tlv_block_t; + +/** + * @brief Function for parsing raw data of File Control TLV, read from a Type 4 Tag. + * + * This function parses raw data of File Control TLV and stores the results in its + * descriptor. + * + * @param[in,out] p_file_control_tlv Pointer to the File Control TLV that will be filled with + * parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw TLV data. + * @param[in,out] p_len In: Buffer length with TLV blocks. + * Out: Total length of first identified TLV within the buffer. + * + * @retval NRF_SUCCESS If operation was successful. + * @retval NRF_ERROR_INVALID_LENGTH If provided buffer length is too small for TLV block. + * @retval NRF_ERROR_INVALID_DATA If any TLV block field contains invalid data. + */ +ret_code_t nfc_t4t_file_control_tlv_parse(nfc_t4t_tlv_block_t * p_file_control_tlv, + uint8_t * p_raw_data, + uint16_t * p_len); + +/** + * @brief Function for printing TLV block descriptor. + * + * This function prints TLV block descriptor. + * + * @param[in] num TLV block number. + * @param[in] p_t4t_tlv_block Pointer to the TLV block descriptor. + */ +void nfc_t4t_file_control_tlv_printout(uint8_t num, nfc_t4t_tlv_block_t * p_t4t_tlv_block); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_T4T_TLV_BLOCK_H__ */ |