prov-acceptor.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <ell/ell.h>
  14. #include "src/shared/ecc.h"
  15. #include "mesh/mesh-defs.h"
  16. #include "mesh/util.h"
  17. #include "mesh/crypto.h"
  18. #include "mesh/net.h"
  19. #include "mesh/prov.h"
  20. #include "mesh/provision.h"
  21. #include "mesh/pb-adv.h"
  22. #include "mesh/mesh.h"
  23. #include "mesh/agent.h"
  24. /* Quick size sanity check */
  25. static const uint16_t expected_pdu_size[] = {
  26. 2, /* PROV_INVITE */
  27. 12, /* PROV_CAPS */
  28. 6, /* PROV_START */
  29. 65, /* PROV_PUB_KEY */
  30. 1, /* PROV_INP_CMPLT */
  31. 17, /* PROV_CONFIRM */
  32. 17, /* PROV_RANDOM */
  33. 34, /* PROV_DATA */
  34. 1, /* PROV_COMPLETE */
  35. 2, /* PROV_FAILED */
  36. };
  37. #define BEACON_TYPE_UNPROVISIONED 0x00
  38. struct deferred_cmd {
  39. uint16_t len;
  40. uint8_t cmd[];
  41. };
  42. static const uint8_t pkt_filter = MESH_AD_TYPE_PROVISION;
  43. static const uint8_t bec_filter[] = {MESH_AD_TYPE_BEACON,
  44. BEACON_TYPE_UNPROVISIONED};
  45. #define MAT_REMOTE_PUBLIC 0x01
  46. #define MAT_LOCAL_PRIVATE 0x02
  47. #define MAT_RAND_AUTH 0x04
  48. #define MAT_SECRET (MAT_REMOTE_PUBLIC | MAT_LOCAL_PRIVATE)
  49. struct mesh_prov_acceptor {
  50. mesh_prov_acceptor_complete_func_t cmplt;
  51. prov_trans_tx_t trans_tx;
  52. struct l_queue *ob;
  53. void *agent;
  54. void *caller_data;
  55. void *trans_data;
  56. struct l_timeout *timeout;
  57. uint32_t to_secs;
  58. uint8_t out_opcode;
  59. uint8_t transport;
  60. uint8_t material;
  61. uint8_t expected;
  62. int8_t previous;
  63. struct conf_input conf_inputs;
  64. uint8_t calc_key[16];
  65. uint8_t salt[16];
  66. uint8_t confirm[16];
  67. uint8_t s_key[16];
  68. uint8_t s_nonce[13];
  69. uint8_t private_key[32];
  70. uint8_t secret[32];
  71. uint8_t rand_auth_workspace[48];
  72. };
  73. static struct mesh_prov_acceptor *prov = NULL;
  74. static void acceptor_free(void)
  75. {
  76. if (!prov)
  77. return;
  78. l_timeout_remove(prov->timeout);
  79. l_queue_destroy(prov->ob, l_free);
  80. mesh_send_cancel(bec_filter, sizeof(bec_filter));
  81. mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
  82. pb_adv_unreg(prov);
  83. l_free(prov);
  84. prov = NULL;
  85. }
  86. static void acp_prov_close(void *user_data, uint8_t reason)
  87. {
  88. struct mesh_prov_acceptor *rx_prov = user_data;
  89. if (rx_prov != prov)
  90. return;
  91. if (reason == PROV_ERR_SUCCESS)
  92. reason = PROV_ERR_UNEXPECTED_ERR;
  93. if (prov->cmplt)
  94. prov->cmplt(prov->caller_data, reason, NULL);
  95. prov->cmplt = NULL;
  96. acceptor_free();
  97. }
  98. static void prov_send(struct mesh_prov_acceptor *prov, void *cmd, uint16_t len)
  99. {
  100. struct deferred_cmd *defer;
  101. if (prov->out_opcode == PROV_NONE) {
  102. prov->out_opcode = *(uint8_t *) cmd;
  103. prov->trans_tx(prov->trans_data, cmd, len);
  104. } else {
  105. defer = l_malloc(len + sizeof(struct deferred_cmd));
  106. defer->len = len;
  107. memcpy(defer->cmd, cmd, len);
  108. l_queue_push_tail(prov->ob, defer);
  109. }
  110. }
  111. static void prov_to(struct l_timeout *timeout, void *user_data)
  112. {
  113. struct mesh_prov_acceptor *rx_prov = user_data;
  114. uint8_t fail_code[2] = {PROV_FAILED, PROV_ERR_UNEXPECTED_ERR};
  115. if (rx_prov != prov)
  116. return;
  117. l_timeout_remove(prov->timeout);
  118. prov->timeout = NULL;
  119. if (prov->cmplt && prov->trans_tx) {
  120. prov->cmplt(prov->caller_data, PROV_ERR_TIMEOUT, NULL);
  121. prov->cmplt = NULL;
  122. prov_send(prov, fail_code, 2);
  123. prov->timeout = l_timeout_create(1, prov_to, prov, NULL);
  124. return;
  125. }
  126. acceptor_free();
  127. }
  128. static void acp_prov_open(void *user_data, prov_trans_tx_t trans_tx,
  129. void *trans_data, uint8_t transport)
  130. {
  131. struct mesh_prov_acceptor *rx_prov = user_data;
  132. /* Only one provisioning session may be open at a time */
  133. if (rx_prov != prov)
  134. return;
  135. /* Only one provisioning session may be open at a time */
  136. if (prov->trans_tx && prov->trans_tx != trans_tx &&
  137. prov->transport != transport)
  138. return;
  139. if (transport != PB_ADV)
  140. return;
  141. prov->trans_tx = trans_tx;
  142. prov->transport = transport;
  143. prov->trans_data = trans_data;
  144. prov->timeout = l_timeout_create(prov->to_secs, prov_to, prov, NULL);
  145. }
  146. static void swap_u256_bytes(uint8_t *u256)
  147. {
  148. int i;
  149. /* End-to-End byte reflection of 32 octet buffer */
  150. for (i = 0; i < 16; i++) {
  151. u256[i] ^= u256[31 - i];
  152. u256[31 - i] ^= u256[i];
  153. u256[i] ^= u256[31 - i];
  154. }
  155. }
  156. static bool prov_calc_secret(const uint8_t *pub, const uint8_t *priv,
  157. uint8_t *secret)
  158. {
  159. uint8_t tmp[64];
  160. /* Convert to ECC byte order */
  161. memcpy(tmp, pub, 64);
  162. swap_u256_bytes(tmp);
  163. swap_u256_bytes(tmp + 32);
  164. if (!ecdh_shared_secret(tmp, priv, secret))
  165. return false;
  166. /* Convert to Mesh byte order */
  167. swap_u256_bytes(secret);
  168. return true;
  169. }
  170. static bool acp_credentials(struct mesh_prov_acceptor *prov)
  171. {
  172. if (!memcmp(prov->conf_inputs.prv_pub_key,
  173. prov->conf_inputs.dev_pub_key, 64))
  174. return false;
  175. if (!prov_calc_secret(prov->conf_inputs.prv_pub_key,
  176. prov->private_key, prov->secret))
  177. return false;
  178. if (!mesh_crypto_s1(&prov->conf_inputs,
  179. sizeof(prov->conf_inputs), prov->salt))
  180. return false;
  181. if (!mesh_crypto_prov_conf_key(prov->secret, prov->salt,
  182. prov->calc_key))
  183. return false;
  184. l_getrandom(prov->rand_auth_workspace, 16);
  185. print_packet("PublicKeyProv", prov->conf_inputs.prv_pub_key, 64);
  186. print_packet("PublicKeyDev", prov->conf_inputs.dev_pub_key, 64);
  187. /* Normalize for debug out -- No longer needed for calculations */
  188. swap_u256_bytes(prov->private_key);
  189. print_packet("PrivateKeyLocal", prov->private_key, 32);
  190. print_packet("ConfirmationInputs", &prov->conf_inputs,
  191. sizeof(prov->conf_inputs));
  192. print_packet("ECDHSecret", prov->secret, 32);
  193. print_packet("LocalRandom", prov->rand_auth_workspace, 16);
  194. print_packet("ConfirmationSalt", prov->salt, 16);
  195. print_packet("ConfirmationKey", prov->calc_key, 16);
  196. return true;
  197. }
  198. static uint32_t digit_mod(uint8_t power)
  199. {
  200. uint32_t ret = 1;
  201. while (power--)
  202. ret *= 10;
  203. return ret;
  204. }
  205. static void number_cb(void *user_data, int err, uint32_t number)
  206. {
  207. struct mesh_prov_acceptor *rx_prov = user_data;
  208. struct prov_fail_msg msg;
  209. if (prov != rx_prov)
  210. return;
  211. if (err) {
  212. msg.opcode = PROV_FAILED;
  213. msg.reason = PROV_ERR_UNEXPECTED_ERR;
  214. prov_send(prov, &msg, sizeof(msg));
  215. return;
  216. }
  217. /* Save two copies, to generate two confirmation values */
  218. l_put_be32(number, prov->rand_auth_workspace + 28);
  219. l_put_be32(number, prov->rand_auth_workspace + 44);
  220. prov->material |= MAT_RAND_AUTH;
  221. msg.opcode = PROV_INP_CMPLT;
  222. prov_send(prov, &msg.opcode, 1);
  223. }
  224. static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
  225. {
  226. struct mesh_prov_acceptor *rx_prov = user_data;
  227. struct prov_fail_msg msg;
  228. if (prov != rx_prov)
  229. return;
  230. if (err || !key || len != 16) {
  231. msg.opcode = PROV_FAILED;
  232. msg.reason = PROV_ERR_UNEXPECTED_ERR;
  233. prov_send(prov, &msg, sizeof(msg));
  234. return;
  235. }
  236. /* Save two copies, to generate two confirmation values */
  237. memcpy(prov->rand_auth_workspace + 16, key, 16);
  238. memcpy(prov->rand_auth_workspace + 32, key, 16);
  239. prov->material |= MAT_RAND_AUTH;
  240. if (prov->conf_inputs.start.auth_action == PROV_ACTION_IN_ALPHA) {
  241. msg.opcode = PROV_INP_CMPLT;
  242. prov_send(prov, &msg.opcode, 1);
  243. }
  244. }
  245. static void priv_key_cb(void *user_data, int err, uint8_t *key, uint32_t len)
  246. {
  247. struct mesh_prov_acceptor *rx_prov = user_data;
  248. struct prov_fail_msg msg;
  249. if (prov != rx_prov)
  250. return;
  251. if (err || !key || len != 32) {
  252. msg.opcode = PROV_FAILED;
  253. msg.reason = PROV_ERR_UNEXPECTED_ERR;
  254. prov_send(prov, &msg, sizeof(msg));
  255. return;
  256. }
  257. /* API delivers Mesh byte order, switch to little endian */
  258. swap_u256_bytes(key);
  259. memcpy(prov->private_key, key, 32);
  260. ecc_make_public_key(prov->private_key,
  261. prov->conf_inputs.dev_pub_key);
  262. /* Convert Public key to Mesh byte order */
  263. swap_u256_bytes(prov->conf_inputs.dev_pub_key);
  264. swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
  265. prov->material |= MAT_LOCAL_PRIVATE;
  266. if ((prov->material & MAT_SECRET) == MAT_SECRET) {
  267. if (!acp_credentials(prov)) {
  268. msg.opcode = PROV_FAILED;
  269. msg.reason = PROV_ERR_UNEXPECTED_ERR;
  270. prov_send(prov, &msg, sizeof(msg));
  271. }
  272. }
  273. }
  274. static void send_caps(struct mesh_prov_acceptor *prov)
  275. {
  276. struct prov_caps_msg msg;
  277. msg.opcode = PROV_CAPS;
  278. memcpy(&msg.caps, &prov->conf_inputs.caps,
  279. sizeof(prov->conf_inputs.caps));
  280. prov->expected = PROV_START;
  281. prov_send(prov, &msg, sizeof(msg));
  282. }
  283. static void send_pub_key(struct mesh_prov_acceptor *prov)
  284. {
  285. struct prov_pub_key_msg msg;
  286. msg.opcode = PROV_PUB_KEY;
  287. memcpy(msg.pub_key, prov->conf_inputs.dev_pub_key, sizeof(msg.pub_key));
  288. prov_send(prov, &msg, sizeof(msg));
  289. }
  290. static bool send_conf(struct mesh_prov_acceptor *prov)
  291. {
  292. struct prov_conf_msg msg;
  293. msg.opcode = PROV_CONFIRM;
  294. mesh_crypto_aes_cmac(prov->calc_key, prov->rand_auth_workspace, 32,
  295. msg.conf);
  296. /* Fail if confirmations match */
  297. if (!memcmp(msg.conf, prov->confirm, sizeof(msg.conf)))
  298. return false;
  299. prov_send(prov, &msg, sizeof(msg));
  300. return true;
  301. }
  302. static void send_rand(struct mesh_prov_acceptor *prov)
  303. {
  304. struct prov_rand_msg msg;
  305. msg.opcode = PROV_RANDOM;
  306. memcpy(msg.rand, prov->rand_auth_workspace, sizeof(msg.rand));
  307. prov_send(prov, &msg, sizeof(msg));
  308. }
  309. static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
  310. {
  311. struct mesh_prov_acceptor *rx_prov = user_data;
  312. struct mesh_prov_node_info *info;
  313. struct prov_fail_msg fail;
  314. uint8_t type = *data++;
  315. uint32_t oob_key;
  316. uint64_t decode_mic;
  317. bool result;
  318. if (rx_prov != prov || !prov->trans_tx)
  319. return;
  320. l_debug("Provisioning packet received type: %2.2x (%u octets)",
  321. type, len);
  322. if (type == prov->previous) {
  323. l_error("Ignore repeated %2.2x packet", type);
  324. return;
  325. } else if (type > prov->expected || type < prov->previous) {
  326. l_error("Expected %2.2x, Got:%2.2x", prov->expected, type);
  327. fail.reason = PROV_ERR_UNEXPECTED_PDU;
  328. goto failure;
  329. }
  330. if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
  331. len != expected_pdu_size[type]) {
  332. l_error("Expected PDU size %d, Got %d (type: %2.2x)",
  333. len, expected_pdu_size[type], type);
  334. fail.reason = PROV_ERR_INVALID_FORMAT;
  335. goto failure;
  336. }
  337. switch (type){
  338. case PROV_INVITE: /* Prov Invite */
  339. prov->conf_inputs.invite.attention = data[0];
  340. send_caps(prov);
  341. break;
  342. case PROV_START: /* Prov Start */
  343. memcpy(&prov->conf_inputs.start, data,
  344. sizeof(prov->conf_inputs.start));
  345. if (prov->conf_inputs.start.algorithm ||
  346. prov->conf_inputs.start.pub_key > 1 ||
  347. prov->conf_inputs.start.auth_method > 3) {
  348. fail.reason = PROV_ERR_INVALID_FORMAT;
  349. goto failure;
  350. }
  351. if (prov->conf_inputs.start.pub_key) {
  352. if (prov->conf_inputs.caps.pub_type) {
  353. /* Prompt Agent for Private Key of OOB */
  354. mesh_agent_request_private_key(prov->agent,
  355. priv_key_cb, prov);
  356. } else {
  357. fail.reason = PROV_ERR_INVALID_PDU;
  358. goto failure;
  359. }
  360. } else {
  361. /* Ephemeral Public Key requested */
  362. ecc_make_key(prov->conf_inputs.dev_pub_key,
  363. prov->private_key);
  364. swap_u256_bytes(prov->conf_inputs.dev_pub_key);
  365. swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
  366. prov->material |= MAT_LOCAL_PRIVATE;
  367. }
  368. prov->expected = PROV_PUB_KEY;
  369. break;
  370. case PROV_PUB_KEY: /* Public Key */
  371. /* Save Key */
  372. memcpy(prov->conf_inputs.prv_pub_key, data, 64);
  373. prov->material |= MAT_REMOTE_PUBLIC;
  374. prov->expected = PROV_CONFIRM;
  375. if ((prov->material & MAT_SECRET) != MAT_SECRET)
  376. return;
  377. if (!acp_credentials(prov)) {
  378. fail.reason = PROV_ERR_UNEXPECTED_ERR;
  379. goto failure;
  380. }
  381. if (!prov->conf_inputs.start.pub_key)
  382. send_pub_key(prov);
  383. /* Start Step 3 */
  384. switch (prov->conf_inputs.start.auth_method) {
  385. default:
  386. case 0:
  387. /* Auth Type 3c - No OOB */
  388. break;
  389. case 1:
  390. /* Auth Type 3c - Static OOB */
  391. /* Prompt Agent for Static OOB */
  392. fail.reason = mesh_agent_request_static(prov->agent,
  393. static_cb, prov);
  394. if (fail.reason)
  395. goto failure;
  396. break;
  397. case 2:
  398. /* Auth Type 3a - Output OOB */
  399. l_getrandom(&oob_key, sizeof(oob_key));
  400. oob_key %= digit_mod(prov->conf_inputs.start.auth_size);
  401. /* Save two copies, for two confirmation values */
  402. l_put_be32(oob_key, prov->rand_auth_workspace + 28);
  403. l_put_be32(oob_key, prov->rand_auth_workspace + 44);
  404. prov->material |= MAT_RAND_AUTH;
  405. if (prov->conf_inputs.start.auth_action ==
  406. PROV_ACTION_OUT_ALPHA) {
  407. /* TODO: Construst NUL-term string to pass */
  408. fail.reason = mesh_agent_display_string(
  409. prov->agent, NULL, NULL, prov);
  410. } else {
  411. /* Ask Agent to Display U32 */
  412. fail.reason = mesh_agent_display_number(
  413. prov->agent, false,
  414. prov->conf_inputs.start.auth_action,
  415. oob_key, NULL, prov);
  416. }
  417. if (fail.reason)
  418. goto failure;
  419. break;
  420. case 3:
  421. /* Auth Type 3b - input OOB */
  422. /* Prompt Agent for Input OOB */
  423. if (prov->conf_inputs.start.auth_action ==
  424. PROV_ACTION_IN_ALPHA) {
  425. fail.reason = mesh_agent_prompt_alpha(
  426. prov->agent, false,
  427. static_cb, prov);
  428. } else {
  429. fail.reason = mesh_agent_prompt_number(
  430. prov->agent, false,
  431. prov->conf_inputs.start.auth_action,
  432. number_cb, prov);
  433. }
  434. if (fail.reason)
  435. goto failure;
  436. break;
  437. }
  438. prov->expected = PROV_CONFIRM;
  439. break;
  440. case PROV_CONFIRM: /* Confirmation */
  441. /* Save Provisioners confirmation for later compare */
  442. memcpy(prov->confirm, data, 16);
  443. prov->expected = PROV_RANDOM;
  444. if (!send_conf(prov)) {
  445. fail.reason = PROV_ERR_INVALID_PDU;
  446. goto failure;
  447. }
  448. break;
  449. case PROV_RANDOM: /* Random Value */
  450. /* Disallow matching random values */
  451. if (!memcmp(prov->rand_auth_workspace, data, 16)) {
  452. fail.reason = PROV_ERR_INVALID_PDU;
  453. goto failure;
  454. }
  455. /* Calculate Session key (needed later) while data is fresh */
  456. mesh_crypto_prov_prov_salt(prov->salt, data,
  457. prov->rand_auth_workspace,
  458. prov->salt);
  459. mesh_crypto_session_key(prov->secret, prov->salt, prov->s_key);
  460. mesh_crypto_nonce(prov->secret, prov->salt, prov->s_nonce);
  461. /* Calculate expected Provisioner Confirm */
  462. memcpy(prov->rand_auth_workspace + 16, data, 16);
  463. mesh_crypto_aes_cmac(prov->calc_key,
  464. prov->rand_auth_workspace + 16, 32,
  465. prov->calc_key);
  466. /* Compare our calculation with Provisioners */
  467. if (memcmp(prov->calc_key, prov->confirm, 16)) {
  468. fail.reason = PROV_ERR_CONFIRM_FAILED;
  469. goto failure;
  470. }
  471. /* Send Random value we used */
  472. send_rand(prov);
  473. prov->expected = PROV_DATA;
  474. break;
  475. case PROV_DATA: /* Provisioning Data */
  476. /* Calculate our device key */
  477. mesh_crypto_device_key(prov->secret,
  478. prov->salt,
  479. prov->calc_key);
  480. /* Decrypt new node data into workspace */
  481. mesh_crypto_aes_ccm_decrypt(prov->s_nonce, prov->s_key,
  482. NULL, 0,
  483. data, len - 1, prov->rand_auth_workspace,
  484. &decode_mic, sizeof(decode_mic));
  485. /* Validate that the data hasn't been messed with in transit */
  486. if (l_get_be64(data + 25) != decode_mic) {
  487. l_error("Provisioning Failed-MIC compare");
  488. fail.reason = PROV_ERR_DECRYPT_FAILED;
  489. goto failure;
  490. }
  491. info = l_malloc(sizeof(struct mesh_prov_node_info));
  492. memcpy(info->device_key, prov->calc_key, 16);
  493. memcpy(info->net_key, prov->rand_auth_workspace, 16);
  494. info->net_index = l_get_be16(prov->rand_auth_workspace + 16);
  495. info->flags = prov->rand_auth_workspace[18];
  496. info->iv_index = l_get_be32(prov->rand_auth_workspace + 19);
  497. info->unicast = l_get_be16(prov->rand_auth_workspace + 23);
  498. result = prov->cmplt(prov->caller_data, PROV_ERR_SUCCESS, info);
  499. prov->cmplt = NULL;
  500. l_free(info);
  501. if (result) {
  502. prov->rand_auth_workspace[0] = PROV_COMPLETE;
  503. prov_send(prov, prov->rand_auth_workspace, 1);
  504. goto cleanup;
  505. } else {
  506. fail.reason = PROV_ERR_UNEXPECTED_ERR;
  507. goto failure;
  508. }
  509. break;
  510. case PROV_FAILED: /* Provisioning Error -- abort */
  511. /* TODO: Call Complete Callback (Fail)*/
  512. prov->cmplt(prov->caller_data,
  513. data[0] ? data[0] : PROV_ERR_UNEXPECTED_ERR,
  514. NULL);
  515. prov->cmplt = NULL;
  516. goto cleanup;
  517. }
  518. if (prov)
  519. prov->previous = type;
  520. return;
  521. failure:
  522. fail.opcode = PROV_FAILED;
  523. prov_send(prov, &fail, sizeof(fail));
  524. if (prov->cmplt)
  525. prov->cmplt(prov->caller_data, fail.reason, NULL);
  526. prov->cmplt = NULL;
  527. cleanup:
  528. l_timeout_remove(prov->timeout);
  529. /* Give PB Link 5 seconds to end session */
  530. prov->timeout = l_timeout_create(5, prov_to, prov, NULL);
  531. }
  532. static void acp_prov_ack(void *user_data, uint8_t msg_num)
  533. {
  534. struct mesh_prov_acceptor *rx_prov = user_data;
  535. struct deferred_cmd *deferred;
  536. if (rx_prov != prov)
  537. return;
  538. if (prov->out_opcode == PROV_NONE)
  539. return;
  540. prov->out_opcode = PROV_NONE;
  541. deferred = l_queue_pop_head(prov->ob);
  542. if (!deferred)
  543. return;
  544. prov_send(prov, deferred->cmd, deferred->len);
  545. l_free(deferred);
  546. }
  547. /* This starts unprovisioned device beacon */
  548. bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
  549. uint16_t algorithms, uint32_t timeout,
  550. struct mesh_agent *agent,
  551. mesh_prov_acceptor_complete_func_t complete_cb,
  552. void *caller_data)
  553. {
  554. struct mesh_agent_prov_caps *caps;
  555. uint8_t beacon[24] = {MESH_AD_TYPE_BEACON,
  556. BEACON_TYPE_UNPROVISIONED};
  557. uint8_t len = sizeof(beacon) - sizeof(uint32_t);
  558. bool result;
  559. /* Invoked from Join() method in mesh-api.txt, to join a
  560. * remote mesh network.
  561. */
  562. if (prov)
  563. return false;
  564. prov = l_new(struct mesh_prov_acceptor, 1);
  565. prov->to_secs = timeout;
  566. prov->agent = agent;
  567. prov->cmplt = complete_cb;
  568. prov->ob = l_queue_new();
  569. prov->previous = -1;
  570. prov->out_opcode = PROV_NONE;
  571. prov->caller_data = caller_data;
  572. caps = mesh_agent_get_caps(agent);
  573. /* TODO: Should we sanity check values here or elsewhere? */
  574. prov->conf_inputs.caps.num_ele = num_ele;
  575. prov->conf_inputs.caps.pub_type = caps->pub_type;
  576. prov->conf_inputs.caps.static_type = caps->static_type;
  577. prov->conf_inputs.caps.output_size = caps->output_size;
  578. prov->conf_inputs.caps.input_size = caps->input_size;
  579. /* Store UINT16 values in Over-the-Air order, in packed structure
  580. * for crypto inputs
  581. */
  582. l_put_be16(algorithms, &prov->conf_inputs.caps.algorithms);
  583. l_put_be16(caps->output_action, &prov->conf_inputs.caps.output_action);
  584. l_put_be16(caps->input_action, &prov->conf_inputs.caps.input_action);
  585. /* Compose Unprovisioned Beacon */
  586. memcpy(beacon + 2, uuid, 16);
  587. l_put_be16(caps->oob_info, beacon + 18);
  588. if (caps->oob_info & OOB_INFO_URI_HASH){
  589. l_put_be32(caps->uri_hash, beacon + 20);
  590. len += sizeof(uint32_t);
  591. }
  592. /* Infinitely Beacon until Canceled, or Provisioning Starts */
  593. result = mesh_send_pkt(0, 500, beacon, len);
  594. if (!result)
  595. goto error_fail;
  596. /* Always register for PB-ADV */
  597. result = pb_adv_reg(false, acp_prov_open, acp_prov_close, acp_prov_rx,
  598. acp_prov_ack, uuid, prov);
  599. if (result)
  600. return true;
  601. error_fail:
  602. acceptor_free();
  603. return false;
  604. }
  605. void acceptor_cancel(void *user_data)
  606. {
  607. acceptor_free();
  608. }