es_gatts_write.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 "es_gatts_write.h"
  41. #include "es_adv.h"
  42. #include "es_flash.h"
  43. #include "es_gatts.h"
  44. #include "es_security.h"
  45. static ret_code_t send_write_reply(nrf_ble_escs_t * p_escs, ble_gatts_rw_authorize_reply_params_t * p_reply)
  46. {
  47. VERIFY_PARAM_NOT_NULL(p_escs);
  48. VERIFY_PARAM_NOT_NULL(p_reply);
  49. p_reply->type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
  50. p_reply->params.write.update = 1;
  51. p_reply->params.write.offset = 0;
  52. return es_gatts_send_reply(p_escs, p_reply);
  53. }
  54. /**@brief Function checking if length of event is correct, given the frame data.
  55. *
  56. * @param[in] p_data Written ADV Slot data.
  57. * @param[in] length Written length.
  58. *
  59. * @retval true If length is valid.
  60. * @retval false If length is not valid.
  61. */
  62. static bool length_is_valid(uint8_t const * p_data, uint8_t length)
  63. {
  64. if (length == 0 || (length == 1 && p_data[0] == 0))
  65. {
  66. return true;
  67. }
  68. else
  69. {
  70. switch ((es_frame_type_t)p_data[0])
  71. {
  72. case ES_FRAME_TYPE_UID:
  73. return length == ESCS_UID_WRITE_LENGTH;
  74. case ES_FRAME_TYPE_URL:
  75. return ((length >= ESCS_URL_MIN_WRITE_LENGTH) && (length <= ESCS_URL_WRITE_LENGTH));
  76. case ES_FRAME_TYPE_TLM:
  77. return (length == ESCS_TLM_WRITE_LENGTH);
  78. case ES_FRAME_TYPE_EID:
  79. return ((length == ESCS_EID_WRITE_ECDH_LENGTH) ||
  80. (length == ESCS_EID_WRITE_IDK_LENGTH));
  81. default:
  82. return false;
  83. }
  84. }
  85. }
  86. ret_code_t es_gatts_write_handle_unlocked_write(nrf_ble_escs_t * p_escs,
  87. uint16_t uuid,
  88. uint16_t val_handle,
  89. uint8_t const * p_data,
  90. uint16_t length,
  91. uint8_t active_slot)
  92. {
  93. VERIFY_PARAM_NOT_NULL(p_escs);
  94. VERIFY_PARAM_NOT_NULL(p_data);
  95. ret_code_t err_code;
  96. ble_gatts_rw_authorize_reply_params_t reply = {0};
  97. bool long_write = false;
  98. reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  99. switch (uuid)
  100. {
  101. case BLE_UUID_ESCS_ACTIVE_SLOT_CHAR:
  102. if (*p_data > APP_MAX_ADV_SLOTS - 1)
  103. {
  104. // Invalid Attribute Length: for an attempt to write illegal values.
  105. // The beacon will list the total number of available slots in the
  106. // max_supported_total_slots field in the Capabilities characteristic.
  107. reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
  108. length = 0;
  109. }
  110. break;
  111. case BLE_UUID_ESCS_ADV_INTERVAL_CHAR:
  112. es_adv_interval_set(BYTES_SWAP_16BIT(*(nrf_ble_escs_adv_interval_t *)p_data));
  113. break;
  114. case BLE_UUID_ESCS_RADIO_TX_PWR_CHAR:
  115. es_slot_radio_tx_pwr_set(active_slot, *(nrf_ble_escs_radio_tx_pwr_t *)(p_data));
  116. break;
  117. case BLE_UUID_ESCS_ADV_TX_PWR_CHAR:
  118. // Update slot info so that ADV data will only be read from what is written by client.
  119. es_slot_set_adv_custom_tx_power(active_slot, *(nrf_ble_escs_radio_tx_pwr_t *)(p_data));
  120. break;
  121. case BLE_UUID_ESCS_LOCK_STATE_CHAR:
  122. if (length == 1 && (*p_data == NRF_BLE_ESCS_LOCK_BYTE_LOCK ||
  123. *p_data == NRF_BLE_ESCS_LOCK_BYTE_DISABLE_AUTO_RELOCK))
  124. {
  125. // Do nothing special, allow the write.
  126. }
  127. else if (length == ESCS_LOCK_STATE_NEW_LOCK_CODE_WRITE_LENGTH &&
  128. *p_data == NRF_BLE_ESCS_LOCK_BYTE_LOCK)
  129. {
  130. // 0x00 + key[16] : transition to lock state and update the lock code.
  131. err_code = es_security_lock_code_update((uint8_t*)(p_data) + 1);
  132. RETURN_IF_ERROR(err_code);
  133. // Only write the lock byte (0x00) to the characteristic, so set length to 1.
  134. length = 1;
  135. }
  136. else
  137. {
  138. // Any invalid values locks the characteristic by default.
  139. (*(uint8_t*)p_data) = NRF_BLE_ESCS_LOCK_BYTE_LOCK;
  140. length = 1;
  141. }
  142. break;
  143. case BLE_UUID_ESCS_RW_ADV_SLOT_CHAR:
  144. if (length > 20)
  145. {
  146. long_write = true;
  147. }
  148. reply.params.write.gatt_status = length_is_valid(p_data, length)
  149. ? BLE_GATT_STATUS_SUCCESS
  150. : BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
  151. if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS)
  152. {
  153. es_slot_on_write(active_slot, length, p_data);
  154. es_adv_interval_set(es_adv_interval_get()); // Ensure that valid advertisement interval is used.
  155. }
  156. break;
  157. case BLE_UUID_ESCS_FACTORY_RESET_CHAR:
  158. if (*p_data == 0x0B)
  159. {
  160. err_code = es_flash_factory_reset();
  161. RETURN_IF_ERROR(err_code);
  162. }
  163. break;
  164. case BLE_UUID_ESCS_REMAIN_CONNECTABLE_CHAR:
  165. #if APP_IS_REMAIN_CONNECTABLE_SUPPORTED == ESCS_FUNCT_REMAIN_CONNECTABLE_SUPPORTED_Yes
  166. if (*p_data != 0)
  167. {
  168. es_adv_remain_connectable_set(true);
  169. }
  170. else
  171. {
  172. es_adv_remain_connectable_set(false);
  173. }
  174. #endif
  175. break;
  176. default:
  177. break;
  178. }
  179. reply.params.write.len = length;
  180. reply.params.write.p_data = p_data;
  181. if (!long_write)
  182. {
  183. return send_write_reply(p_escs, &reply);
  184. }
  185. else
  186. {
  187. return NRF_SUCCESS;
  188. }
  189. }
  190. ret_code_t es_gatts_write_handle_unlock(nrf_ble_escs_t * p_escs,
  191. uint8_t const * p_data,
  192. uint16_t length,
  193. uint16_t val_handle)
  194. {
  195. VERIFY_PARAM_NOT_NULL(p_escs);
  196. VERIFY_PARAM_NOT_NULL(p_data);
  197. ret_code_t err_code;
  198. ble_gatts_rw_authorize_reply_params_t reply = {0};
  199. ble_gatts_value_t value = {.len = length, .offset = 0, .p_value = (uint8_t*)p_data};
  200. if (length == ESCS_AES_KEY_SIZE)
  201. {
  202. err_code = sd_ble_gatts_value_set(p_escs->conn_handle, val_handle, &value);
  203. if (err_code == NRF_SUCCESS)
  204. {
  205. reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  206. es_security_unlock_verify((value.p_value));
  207. }
  208. else
  209. {
  210. reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED;
  211. }
  212. }
  213. reply.params.write.len = length;
  214. reply.params.write.p_data = (const uint8_t *)value.p_value;
  215. return send_write_reply(p_escs, &reply);
  216. }