nfc_t4t_tlv_block.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_config.h"
  41. #if NFC_T4T_TLV_BLOCK_PARSER_ENABLED
  42. #include <string.h>
  43. #include "nfc_t4t_tlv_block.h"
  44. #include "app_util.h"
  45. #include "sdk_macros.h"
  46. #include "nordic_common.h"
  47. #define NRF_LOG_MODULE_NAME nfc_t4t_tlv_block_parser
  48. #if NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
  49. #define NRF_LOG_LEVEL NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL
  50. #define NRF_LOG_INFO_COLOR NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR
  51. #include "nrf_log.h"
  52. NRF_LOG_MODULE_REGISTER();
  53. #else // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
  54. #define NRF_LOG_LEVEL 0
  55. #include "nrf_log.h"
  56. #endif // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
  57. #define TLV_TYPE_FIELD_LEN 1U ///< Length of a type field.
  58. /**
  59. * @brief TLV length field related defines.
  60. */
  61. #define TLV_LEN_SHORT_FIELD_LEN 1U ///< Length of a short length field.
  62. #define TLV_LEN_LONG_FIELD_LEN 3U ///< Length of an extended length field.
  63. #define TLV_LEN_LONG_FORMAT_TOKEN 0xFF ///< Value indicating the use of an extended length field.
  64. #define TLV_LEN_LONG_FORMAT_TOKEN_SIZE 1U ///< Size of long format token.
  65. #define TLV_LEN_LONG_FORMAT_MIN_VALUE 0xFF ///< The minimal value of length field that can be used in long format.
  66. /**
  67. * @brief Possible sizes of TLV block.
  68. */
  69. #define TLV_MIN_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_SHORT_FIELD_LEN)
  70. #define TLV_MIN_LONG_FORMAT_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_LONG_FIELD_LEN)
  71. #define TLV_MIN_VALUE_FIELD_SIZE 6U
  72. /**
  73. * @brief Field sizes that are present in TLV block.
  74. */
  75. #define FILE_CONTROL_FILE_ID_FIELD_SIZE 2U
  76. #define FILE_CONTROL_READ_ACCESS_FIELD_SIZE 1U
  77. #define FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE 1U
  78. #define FILE_CONTROL_COMMON_FIELDS_SIZE (FILE_CONTROL_FILE_ID_FIELD_SIZE \
  79. + FILE_CONTROL_READ_ACCESS_FIELD_SIZE \
  80. + FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE)
  81. /**
  82. * @brief Invalid values for File Identifier field.
  83. */
  84. #define FILE_ID_INVALID_VALUE_0 0x0000
  85. #define FILE_ID_INVALID_VALUE_1 0xE102
  86. #define FILE_ID_INVALID_VALUE_2 0xE103
  87. #define FILE_ID_INVALID_VALUE_3 0x3F00
  88. #define FILE_ID_INVALID_VALUE_4 0x3FFF
  89. #define FILE_ID_INVALID_VALUE_5 0xFFFF
  90. /**
  91. * @brief NDEF file related defines.
  92. */
  93. #define NDEF_FILE_MAX_SIZE_FIELD_SIZE 2U
  94. #define NDEF_FILE_MAX_SIZE_MIN_VAL 0x0005
  95. #define NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFE
  96. #define NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
  97. + NDEF_FILE_MAX_SIZE_FIELD_SIZE)
  98. /**
  99. * @brief Proprietary file related defines.
  100. */
  101. #define PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE 2U
  102. #define PROPRIETARY_FILE_MAX_SIZE_MIN_VAL 0x0003
  103. #define PROPRIETARY_FILE_MAX_SIZE_MAX_VAL 0xFFFE
  104. #define PROPRIETARY_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
  105. + PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE)
  106. /**
  107. * @brief Extended NDEF file related defines.
  108. */
  109. #define EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE 4U
  110. #define EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL 0x0000FFFF
  111. #define EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFFFFFE
  112. #define EXTENDED_NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
  113. + EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE)
  114. /**
  115. * @brief Validates maximum file size field range. This field is present in every File Control TLV.
  116. */
  117. #define NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(VALUE, MIN, MAX) \
  118. if ( ( (VALUE) < (MIN) ) || ( (VALUE) > (MAX) ) ) \
  119. { \
  120. return NRF_ERROR_INVALID_DATA; \
  121. }
  122. /**
  123. * @brief Function for validating all possible types of File Control TLV.
  124. */
  125. __STATIC_INLINE ret_code_t nfc_t4t_file_control_tl_validate(nfc_t4t_tlv_block_t * p_file_control_tlv)
  126. {
  127. switch (p_file_control_tlv->type)
  128. {
  129. case NDEF_FILE_CONTROL_TLV:
  130. VERIFY_TRUE(p_file_control_tlv->length == NDEF_FILE_CONTROL_TLV_LEN,
  131. NRF_ERROR_INVALID_DATA);
  132. return NRF_SUCCESS;
  133. case PROPRIETARY_FILE_CONTROL_TLV:
  134. VERIFY_TRUE(p_file_control_tlv->length == PROPRIETARY_FILE_CONTROL_TLV_LEN,
  135. NRF_ERROR_INVALID_DATA);
  136. return NRF_SUCCESS;
  137. case EXTENDED_NDEF_FILE_CONTROL_TLV:
  138. VERIFY_TRUE(p_file_control_tlv->length == EXTENDED_NDEF_FILE_CONTROL_TLV_LEN,
  139. NRF_ERROR_INVALID_DATA);
  140. return NRF_SUCCESS;
  141. default:
  142. return NRF_ERROR_INVALID_DATA;
  143. }
  144. }
  145. /**
  146. * @brief Function for parsing value field of File Control TLV.
  147. */
  148. static ret_code_t nfc_t4t_file_control_value_parse(nfc_t4t_tlv_block_t * p_file_control_tlv,
  149. uint8_t * p_value_buff)
  150. {
  151. nfc_t4t_file_control_val_t * p_control_tlv_val;
  152. // Handle File Identifier field.
  153. p_control_tlv_val = &p_file_control_tlv->value;
  154. p_control_tlv_val->file_id = uint16_big_decode(p_value_buff);
  155. p_value_buff += FILE_CONTROL_FILE_ID_FIELD_SIZE;
  156. switch (p_control_tlv_val->file_id)
  157. {
  158. case FILE_ID_INVALID_VALUE_0:
  159. case FILE_ID_INVALID_VALUE_1:
  160. case FILE_ID_INVALID_VALUE_2:
  161. case FILE_ID_INVALID_VALUE_3:
  162. case FILE_ID_INVALID_VALUE_4:
  163. case FILE_ID_INVALID_VALUE_5:
  164. return NRF_ERROR_INVALID_DATA;
  165. default:
  166. break;
  167. }
  168. // Handle Max file size field.
  169. switch (p_file_control_tlv->type)
  170. {
  171. case NDEF_FILE_CONTROL_TLV:
  172. p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff);
  173. p_value_buff += NDEF_FILE_MAX_SIZE_FIELD_SIZE;
  174. NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
  175. NDEF_FILE_MAX_SIZE_MIN_VAL,
  176. NDEF_FILE_MAX_SIZE_MAX_VAL);
  177. break;
  178. case PROPRIETARY_FILE_CONTROL_TLV:
  179. p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff);
  180. p_value_buff += PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE;
  181. NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
  182. PROPRIETARY_FILE_MAX_SIZE_MIN_VAL,
  183. PROPRIETARY_FILE_MAX_SIZE_MAX_VAL);
  184. break;
  185. case EXTENDED_NDEF_FILE_CONTROL_TLV:
  186. p_control_tlv_val->max_file_size = uint32_big_decode(p_value_buff);
  187. p_value_buff += EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE;
  188. NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
  189. EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL,
  190. EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL);
  191. break;
  192. }
  193. // Handle read access condition field.
  194. p_control_tlv_val->read_access = *p_value_buff;
  195. p_value_buff += FILE_CONTROL_READ_ACCESS_FIELD_SIZE;
  196. // Handle write access condition field.
  197. p_control_tlv_val->write_access = *p_value_buff;
  198. return NRF_SUCCESS;
  199. }
  200. ret_code_t nfc_t4t_file_control_tlv_parse(nfc_t4t_tlv_block_t * p_file_control_tlv,
  201. uint8_t * p_raw_data,
  202. uint16_t * p_len)
  203. {
  204. ret_code_t err_code;
  205. uint8_t * p_offset = p_raw_data;
  206. if (*p_len < TLV_MIN_TL_FIELD_LEN)
  207. {
  208. return NRF_ERROR_INVALID_LENGTH;
  209. }
  210. memset(p_file_control_tlv, 0, sizeof(nfc_t4t_tlv_block_t));
  211. // Handle type field of TLV block.
  212. p_file_control_tlv->type = *p_offset;
  213. p_offset += TLV_TYPE_FIELD_LEN;
  214. // Handle length field of TLV block.
  215. if (*p_offset == TLV_LEN_LONG_FORMAT_TOKEN)
  216. {
  217. if (*p_len < TLV_MIN_LONG_FORMAT_TL_FIELD_LEN)
  218. {
  219. return NRF_ERROR_INVALID_LENGTH;
  220. }
  221. p_file_control_tlv->length = uint16_big_decode(p_offset + TLV_LEN_LONG_FORMAT_TOKEN_SIZE);
  222. p_offset += TLV_LEN_LONG_FIELD_LEN;
  223. if (p_file_control_tlv->length < TLV_LEN_LONG_FORMAT_MIN_VALUE)
  224. {
  225. return NRF_ERROR_INVALID_DATA;
  226. }
  227. }
  228. else
  229. {
  230. p_file_control_tlv->length = *p_offset;
  231. p_offset += TLV_LEN_SHORT_FIELD_LEN;
  232. }
  233. // Calculate the total TLV block size.
  234. uint16_t tlv_block_len = (p_offset - p_raw_data) + p_file_control_tlv->length;
  235. if (*p_len < tlv_block_len)
  236. {
  237. return NRF_ERROR_INVALID_LENGTH;
  238. }
  239. *p_len = tlv_block_len;
  240. // Validate if type and length fields contain values supported by Type 4 Tag.
  241. err_code = nfc_t4t_file_control_tl_validate(p_file_control_tlv);
  242. VERIFY_SUCCESS(err_code);
  243. // Handle value field of TLV block.
  244. err_code = nfc_t4t_file_control_value_parse(p_file_control_tlv, p_offset);
  245. return err_code;
  246. }
  247. void nfc_t4t_file_control_tlv_printout(uint8_t num, nfc_t4t_tlv_block_t * p_t4t_tlv_block)
  248. {
  249. NRF_LOG_INFO("%d file Control TLV", num);
  250. switch (p_t4t_tlv_block->type)
  251. {
  252. case NDEF_FILE_CONTROL_TLV:
  253. NRF_LOG_INFO("Type: NDEF File Control (0x%02x)", p_t4t_tlv_block->type);
  254. break;
  255. case PROPRIETARY_FILE_CONTROL_TLV:
  256. NRF_LOG_INFO("Type: Proprietary File Control (0x%02x)", p_t4t_tlv_block->type);
  257. break;
  258. case EXTENDED_NDEF_FILE_CONTROL_TLV:
  259. NRF_LOG_INFO("Type: Extended NDEF File Control (0x%02x)", p_t4t_tlv_block->type);
  260. break;
  261. default:
  262. NRF_LOG_INFO("Type: Unknown (0x%02x)", p_t4t_tlv_block->type);
  263. }
  264. NRF_LOG_INFO("Length (in bytes): %d", p_t4t_tlv_block->length);
  265. nfc_t4t_file_control_val_t * p_tlv_val = &p_t4t_tlv_block->value;
  266. NRF_LOG_INFO("File Identifier: 0x%04X ", p_tlv_val->file_id);
  267. NRF_LOG_INFO("Maximum file size: %d ", p_tlv_val->max_file_size);
  268. NRF_LOG_INFO("Read access condition: 0x%02X ", p_tlv_val->read_access);
  269. NRF_LOG_INFO("Write access condition: 0x%02x ", p_tlv_val->write_access);
  270. if (p_tlv_val->file.p_content != NULL)
  271. {
  272. NRF_LOG_INFO("NDEF file content present. Length: %d ", p_tlv_val->file.len);
  273. NRF_LOG_HEXDUMP_INFO(p_tlv_val->file.p_content, p_tlv_val->file.len);
  274. }
  275. else
  276. {
  277. NRF_LOG_INFO("NDEF file content is not present ");
  278. }
  279. }
  280. #endif // NFC_T4T_TLV_BLOCK_PARSER_ENABLED