nrf_ble_lesc.c 16 KB

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