nrf_ble_lesc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * Copyright (c) 2018, 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_common.h"
  41. #if NRF_MODULE_ENABLED(NRF_BLE_LESC)
  42. #include "nrf_ble_lesc.h"
  43. #include "nrf_crypto.h"
  44. #define NRF_LOG_MODULE_NAME nrf_ble_lesc
  45. #include "nrf_log.h"
  46. NRF_LOG_MODULE_REGISTER();
  47. /**@brief Descriptor of the peer public key. */
  48. typedef struct
  49. {
  50. nrf_crypto_ecc_public_key_t value; /**< Peer public key. */
  51. volatile bool is_valid; /**< Flag indicating that the public key is valid. */
  52. } nrf_ble_lesc_peer_pub_key_t;
  53. /**@brief The maximum number of peripheral and central connections combined.
  54. * This value is based on what is configured in the SoftDevice handler sdk_config.
  55. */
  56. #define NRF_BLE_LESC_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT)
  57. __ALIGN(4) static ble_gap_lesc_p256_pk_t m_lesc_public_key; /**< LESC ECC Public Key. */
  58. __ALIGN(4) static ble_gap_lesc_dhkey_t m_lesc_dh_key; /**< LESC ECC DH Key. */
  59. static nrf_crypto_ecdh_context_t m_ecdh_context; /**< Context to do the LESC ECDH calculation */
  60. static bool m_ble_lesc_internal_error; /**< Flag indicating that the module encountered an internal error. */
  61. static bool m_keypair_generated; /**< Flag indicating that the local ECDH key pair was generated. */
  62. static nrf_crypto_ecc_key_pair_generate_context_t m_keygen_context; /**< Context to generate private/public key pair. */
  63. static nrf_crypto_ecc_private_key_t m_private_key; /**< Allocated private key type to use for LESC DH generation. */
  64. static nrf_crypto_ecc_public_key_t m_public_key; /**< Allocated public key type to use for LESC DH generation. */
  65. static nrf_ble_lesc_peer_pub_key_t m_peer_keys[NRF_BLE_LESC_LINK_COUNT]; /**< Array of pointers to peer public keys, used for LESC DH generation. */
  66. ret_code_t nrf_ble_lesc_init(void)
  67. {
  68. ret_code_t err_code;
  69. memset((void *) m_peer_keys, 0, sizeof(m_peer_keys));
  70. #if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_NRF_MALLOC
  71. // Initialize mem_manager if used by nrf_crypto.
  72. err_code = nrf_mem_init();
  73. if (err_code != NRF_SUCCESS)
  74. {
  75. NRF_LOG_ERROR("nrf_mem_init() returned error 0x%x.", err_code);
  76. return err_code;
  77. }
  78. #endif
  79. // Ensure that nrf_crypto has been initialized.
  80. err_code = nrf_crypto_init();
  81. if (err_code != NRF_SUCCESS)
  82. {
  83. NRF_LOG_ERROR("nrf_crypto_init() returned error 0x%x.", err_code);
  84. return err_code;
  85. }
  86. NRF_LOG_DEBUG("Initialized nrf_crypto.");
  87. #if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1)
  88. // Do nothing. RNG is initialized with nrf_crypto_init call.
  89. #elif defined((NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0)
  90. // Initialize the RNG.
  91. err_code = nrf_crypto_rng_init(NULL, NULL);
  92. if (err_code != NRF_SUCCESS)
  93. {
  94. NRF_LOG_ERROR("nrf_crypto_rng_init() returned error 0x%x.", err_code);
  95. return err_code;
  96. }
  97. #else
  98. #error Invalid sdk_config.h (does not contain NRF_CRYPTO_RNG_AUTO_INIT_ENABLED)
  99. #endif // defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1)
  100. NRF_LOG_DEBUG("Initialized nrf_ble_lesc.");
  101. // Reset module state.
  102. m_ble_lesc_internal_error = false;
  103. m_keypair_generated = false;
  104. // Generate ECC key pair. Only one key pair is automatically generated by this module.
  105. err_code = nrf_ble_lesc_keypair_generate();
  106. return err_code;
  107. }
  108. ret_code_t nrf_ble_lesc_keypair_generate(void)
  109. {
  110. ret_code_t err_code;
  111. size_t public_len = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE;
  112. // Check if any DH computation is pending
  113. for (uint32_t i = 0; i < ARRAY_SIZE(m_peer_keys); i++)
  114. {
  115. if (m_peer_keys[i].is_valid)
  116. {
  117. return NRF_ERROR_BUSY;
  118. }
  119. }
  120. // Update flag to indicate that there is no valid private key.
  121. m_keypair_generated = false;
  122. NRF_LOG_DEBUG("Generating ECC key pair");
  123. err_code = nrf_crypto_ecc_key_pair_generate(&m_keygen_context,
  124. &g_nrf_crypto_ecc_secp256r1_curve_info,
  125. &m_private_key,
  126. &m_public_key);
  127. if (err_code != NRF_SUCCESS)
  128. {
  129. NRF_LOG_ERROR("nrf_crypto_ecc_key_pair_generate() returned error 0x%x.", err_code);
  130. return err_code;
  131. }
  132. // Convert to a raw type.
  133. err_code = nrf_crypto_ecc_public_key_to_raw(&m_public_key,
  134. m_lesc_public_key.pk,
  135. &public_len);
  136. if (err_code != NRF_SUCCESS)
  137. {
  138. NRF_LOG_ERROR("nrf_crypto_ecc_public_key_to_raw() returned error 0x%x.", err_code);
  139. return err_code;
  140. }
  141. // Invert the raw type to little-endian (required for BLE).
  142. err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
  143. m_lesc_public_key.pk,
  144. m_lesc_public_key.pk,
  145. NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE);
  146. if (err_code != NRF_SUCCESS)
  147. {
  148. NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code);
  149. }
  150. else
  151. {
  152. // Set the flag to indicate that there is a valid ECDH key pair generated.
  153. m_keypair_generated = true;
  154. }
  155. return err_code;
  156. }
  157. ble_gap_lesc_p256_pk_t * nrf_ble_lesc_public_key_get(void)
  158. {
  159. ble_gap_lesc_p256_pk_t * p_lesc_pk = NULL;
  160. if (m_keypair_generated)
  161. {
  162. p_lesc_pk = &m_lesc_public_key;
  163. }
  164. else
  165. {
  166. NRF_LOG_ERROR("Trying to access LESC public key that has not been generated yet.");
  167. }
  168. return p_lesc_pk;
  169. }
  170. /**@brief Function for calculating a DH key and responding to the DH key request on a given
  171. * connection handle.
  172. *
  173. * @param[in] p_peer_public_key ECC peer public key, used to compute shared secret.
  174. * @param[in] conn_handle Connection handle.
  175. *
  176. * @retval NRF_SUCCESS If the operation was successful.
  177. * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecdh_compute, @ref
  178. * nrf_crypto_ecc_byte_order_invert, and @ref sd_ble_gap_lesc_dhkey_reply functions.
  179. */
  180. static ret_code_t compute_and_give_dhkey(nrf_ble_lesc_peer_pub_key_t * p_peer_public_key,
  181. uint16_t conn_handle)
  182. {
  183. ret_code_t err_code = NRF_ERROR_INTERNAL;
  184. size_t shared_secret_size = BLE_GAP_LESC_DHKEY_LEN;
  185. uint8_t * p_shared_secret = m_lesc_dh_key.key;
  186. // Check if there is a valid generated and set a local ECDH public key.
  187. if (!m_keypair_generated)
  188. {
  189. return NRF_ERROR_INTERNAL;
  190. }
  191. // Check if the public_key is valid
  192. if (p_peer_public_key->is_valid)
  193. {
  194. err_code = nrf_crypto_ecdh_compute(&m_ecdh_context,
  195. &m_private_key,
  196. &p_peer_public_key->value,
  197. p_shared_secret,
  198. &shared_secret_size);
  199. }
  200. if (err_code == NRF_SUCCESS)
  201. {
  202. // Invert the shared secret for little endian format.
  203. err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
  204. p_shared_secret,
  205. p_shared_secret,
  206. BLE_GAP_LESC_DHKEY_LEN);
  207. VERIFY_SUCCESS(err_code);
  208. }
  209. else
  210. {
  211. NRF_LOG_WARNING("Creating invalid shared secret to make LESC fail.");
  212. err_code = nrf_crypto_rng_vector_generate(p_shared_secret, BLE_GAP_LESC_DHKEY_LEN);
  213. VERIFY_SUCCESS(err_code);
  214. }
  215. NRF_LOG_INFO("Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: %d", conn_handle);
  216. err_code = sd_ble_gap_lesc_dhkey_reply(conn_handle, &m_lesc_dh_key);
  217. return err_code;
  218. }
  219. ret_code_t nrf_ble_lesc_request_handler(void)
  220. {
  221. ret_code_t err_code = NRF_SUCCESS;
  222. // If the LESC module is in an invalid state, a restart is required.
  223. if (m_ble_lesc_internal_error)
  224. {
  225. return NRF_ERROR_INTERNAL;
  226. }
  227. for (uint16_t i = 0; i < NRF_BLE_LESC_LINK_COUNT; i++)
  228. {
  229. if (m_peer_keys[i].is_valid)
  230. {
  231. err_code = compute_and_give_dhkey(&m_peer_keys[i], i);
  232. m_peer_keys[i].is_valid = false;
  233. VERIFY_SUCCESS(err_code);
  234. }
  235. }
  236. return err_code;
  237. }
  238. /**@brief Function for handling a DH key request event.
  239. *
  240. * @param[in] conn_handle Connection handle.
  241. * @param[in] p_dhkey_request DH key request descriptor.
  242. *
  243. * @retval NRF_SUCCESS If the operation was successful.
  244. * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecc_byte_order_invert
  245. * and @ref nrf_crypto_ecc_public_key_from_raw functions.
  246. */
  247. static ret_code_t on_dhkey_request(uint16_t conn_handle,
  248. ble_gap_evt_lesc_dhkey_request_t const * p_dhkey_request)
  249. {
  250. ret_code_t err_code = NRF_SUCCESS;
  251. uint8_t public_raw[BLE_GAP_LESC_P256_PK_LEN];
  252. uint8_t * p_public_raw;
  253. size_t public_raw_len;
  254. // Convert the received public key from big-endian to little endian.
  255. p_public_raw = p_dhkey_request->p_pk_peer->pk;
  256. public_raw_len = BLE_GAP_LESC_P256_PK_LEN;
  257. err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
  258. p_public_raw,
  259. public_raw,
  260. public_raw_len);
  261. if (err_code != NRF_SUCCESS)
  262. {
  263. NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code);
  264. return err_code;
  265. }
  266. // Copy peer public key to the allocated context. The dhkey calculation will be performed in
  267. // @ref nrf_ble_lesc_request_handler, so it does not block normal operation.
  268. err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
  269. &m_peer_keys[conn_handle].value,
  270. public_raw,
  271. public_raw_len);
  272. if (err_code != NRF_SUCCESS)
  273. {
  274. NRF_LOG_ERROR("nrf_crypto_ecc_public_key_from_raw() returned error 0x%x.", err_code);
  275. m_peer_keys[conn_handle].is_valid = false;
  276. }
  277. else
  278. {
  279. m_peer_keys[conn_handle].is_valid = true;
  280. }
  281. return NRF_SUCCESS;
  282. }
  283. void nrf_ble_lesc_on_ble_evt(ble_evt_t const * p_ble_evt)
  284. {
  285. ret_code_t err_code = NRF_SUCCESS;
  286. uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
  287. switch (p_ble_evt->header.evt_id)
  288. {
  289. case BLE_GAP_EVT_DISCONNECTED:
  290. m_peer_keys[conn_handle].is_valid = false;
  291. break;
  292. case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
  293. NRF_LOG_DEBUG("BLE_GAP_EVT_LESC_DHKEY_REQUEST");
  294. err_code = on_dhkey_request(conn_handle,
  295. &p_ble_evt->evt.gap_evt.params.lesc_dhkey_request);
  296. if (err_code != NRF_SUCCESS)
  297. {
  298. m_ble_lesc_internal_error = true;
  299. }
  300. break;
  301. default:
  302. break;
  303. }
  304. }
  305. #endif // NRF_BLE_LESC_ENABLED