| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <ell/ell.h>
- #include "src/shared/ecc.h"
- #include "mesh/mesh-defs.h"
- #include "mesh/util.h"
- #include "mesh/crypto.h"
- #include "mesh/net.h"
- #include "mesh/prov.h"
- #include "mesh/provision.h"
- #include "mesh/pb-adv.h"
- #include "mesh/mesh.h"
- #include "mesh/agent.h"
- /* Quick size sanity check */
- static const uint16_t expected_pdu_size[] = {
- 2, /* PROV_INVITE */
- 12, /* PROV_CAPS */
- 6, /* PROV_START */
- 65, /* PROV_PUB_KEY */
- 1, /* PROV_INP_CMPLT */
- 17, /* PROV_CONFIRM */
- 17, /* PROV_RANDOM */
- 34, /* PROV_DATA */
- 1, /* PROV_COMPLETE */
- 2, /* PROV_FAILED */
- };
- #define BEACON_TYPE_UNPROVISIONED 0x00
- struct deferred_cmd {
- uint16_t len;
- uint8_t cmd[];
- };
- static const uint8_t pkt_filter = MESH_AD_TYPE_PROVISION;
- static const uint8_t bec_filter[] = {MESH_AD_TYPE_BEACON,
- BEACON_TYPE_UNPROVISIONED};
- #define MAT_REMOTE_PUBLIC 0x01
- #define MAT_LOCAL_PRIVATE 0x02
- #define MAT_RAND_AUTH 0x04
- #define MAT_SECRET (MAT_REMOTE_PUBLIC | MAT_LOCAL_PRIVATE)
- struct mesh_prov_acceptor {
- mesh_prov_acceptor_complete_func_t cmplt;
- prov_trans_tx_t trans_tx;
- struct l_queue *ob;
- void *agent;
- void *caller_data;
- void *trans_data;
- struct l_timeout *timeout;
- uint32_t to_secs;
- uint8_t out_opcode;
- uint8_t transport;
- uint8_t material;
- uint8_t expected;
- int8_t previous;
- struct conf_input conf_inputs;
- uint8_t calc_key[16];
- uint8_t salt[16];
- uint8_t confirm[16];
- uint8_t s_key[16];
- uint8_t s_nonce[13];
- uint8_t private_key[32];
- uint8_t secret[32];
- uint8_t rand_auth_workspace[48];
- };
- static struct mesh_prov_acceptor *prov = NULL;
- static void acceptor_free(void)
- {
- if (!prov)
- return;
- l_timeout_remove(prov->timeout);
- l_queue_destroy(prov->ob, l_free);
- mesh_send_cancel(bec_filter, sizeof(bec_filter));
- mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
- pb_adv_unreg(prov);
- l_free(prov);
- prov = NULL;
- }
- static void acp_prov_close(void *user_data, uint8_t reason)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- if (rx_prov != prov)
- return;
- if (reason == PROV_ERR_SUCCESS)
- reason = PROV_ERR_UNEXPECTED_ERR;
- if (prov->cmplt)
- prov->cmplt(prov->caller_data, reason, NULL);
- prov->cmplt = NULL;
- acceptor_free();
- }
- static void prov_send(struct mesh_prov_acceptor *prov, void *cmd, uint16_t len)
- {
- struct deferred_cmd *defer;
- if (prov->out_opcode == PROV_NONE) {
- prov->out_opcode = *(uint8_t *) cmd;
- prov->trans_tx(prov->trans_data, cmd, len);
- } else {
- defer = l_malloc(len + sizeof(struct deferred_cmd));
- defer->len = len;
- memcpy(defer->cmd, cmd, len);
- l_queue_push_tail(prov->ob, defer);
- }
- }
- static void prov_to(struct l_timeout *timeout, void *user_data)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- uint8_t fail_code[2] = {PROV_FAILED, PROV_ERR_UNEXPECTED_ERR};
- if (rx_prov != prov)
- return;
- l_timeout_remove(prov->timeout);
- prov->timeout = NULL;
- if (prov->cmplt && prov->trans_tx) {
- prov->cmplt(prov->caller_data, PROV_ERR_TIMEOUT, NULL);
- prov->cmplt = NULL;
- prov_send(prov, fail_code, 2);
- prov->timeout = l_timeout_create(1, prov_to, prov, NULL);
- return;
- }
- acceptor_free();
- }
- static void acp_prov_open(void *user_data, prov_trans_tx_t trans_tx,
- void *trans_data, uint8_t transport)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- /* Only one provisioning session may be open at a time */
- if (rx_prov != prov)
- return;
- /* Only one provisioning session may be open at a time */
- if (prov->trans_tx && prov->trans_tx != trans_tx &&
- prov->transport != transport)
- return;
- if (transport != PB_ADV)
- return;
- prov->trans_tx = trans_tx;
- prov->transport = transport;
- prov->trans_data = trans_data;
- prov->timeout = l_timeout_create(prov->to_secs, prov_to, prov, NULL);
- }
- static void swap_u256_bytes(uint8_t *u256)
- {
- int i;
- /* End-to-End byte reflection of 32 octet buffer */
- for (i = 0; i < 16; i++) {
- u256[i] ^= u256[31 - i];
- u256[31 - i] ^= u256[i];
- u256[i] ^= u256[31 - i];
- }
- }
- static bool prov_calc_secret(const uint8_t *pub, const uint8_t *priv,
- uint8_t *secret)
- {
- uint8_t tmp[64];
- /* Convert to ECC byte order */
- memcpy(tmp, pub, 64);
- swap_u256_bytes(tmp);
- swap_u256_bytes(tmp + 32);
- if (!ecdh_shared_secret(tmp, priv, secret))
- return false;
- /* Convert to Mesh byte order */
- swap_u256_bytes(secret);
- return true;
- }
- static bool acp_credentials(struct mesh_prov_acceptor *prov)
- {
- if (!memcmp(prov->conf_inputs.prv_pub_key,
- prov->conf_inputs.dev_pub_key, 64))
- return false;
- if (!prov_calc_secret(prov->conf_inputs.prv_pub_key,
- prov->private_key, prov->secret))
- return false;
- if (!mesh_crypto_s1(&prov->conf_inputs,
- sizeof(prov->conf_inputs), prov->salt))
- return false;
- if (!mesh_crypto_prov_conf_key(prov->secret, prov->salt,
- prov->calc_key))
- return false;
- l_getrandom(prov->rand_auth_workspace, 16);
- print_packet("PublicKeyProv", prov->conf_inputs.prv_pub_key, 64);
- print_packet("PublicKeyDev", prov->conf_inputs.dev_pub_key, 64);
- /* Normalize for debug out -- No longer needed for calculations */
- swap_u256_bytes(prov->private_key);
- print_packet("PrivateKeyLocal", prov->private_key, 32);
- print_packet("ConfirmationInputs", &prov->conf_inputs,
- sizeof(prov->conf_inputs));
- print_packet("ECDHSecret", prov->secret, 32);
- print_packet("LocalRandom", prov->rand_auth_workspace, 16);
- print_packet("ConfirmationSalt", prov->salt, 16);
- print_packet("ConfirmationKey", prov->calc_key, 16);
- return true;
- }
- static uint32_t digit_mod(uint8_t power)
- {
- uint32_t ret = 1;
- while (power--)
- ret *= 10;
- return ret;
- }
- static void number_cb(void *user_data, int err, uint32_t number)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- struct prov_fail_msg msg;
- if (prov != rx_prov)
- return;
- if (err) {
- msg.opcode = PROV_FAILED;
- msg.reason = PROV_ERR_UNEXPECTED_ERR;
- prov_send(prov, &msg, sizeof(msg));
- return;
- }
- /* Save two copies, to generate two confirmation values */
- l_put_be32(number, prov->rand_auth_workspace + 28);
- l_put_be32(number, prov->rand_auth_workspace + 44);
- prov->material |= MAT_RAND_AUTH;
- msg.opcode = PROV_INP_CMPLT;
- prov_send(prov, &msg.opcode, 1);
- }
- static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- struct prov_fail_msg msg;
- if (prov != rx_prov)
- return;
- if (err || !key || len != 16) {
- msg.opcode = PROV_FAILED;
- msg.reason = PROV_ERR_UNEXPECTED_ERR;
- prov_send(prov, &msg, sizeof(msg));
- return;
- }
- /* Save two copies, to generate two confirmation values */
- memcpy(prov->rand_auth_workspace + 16, key, 16);
- memcpy(prov->rand_auth_workspace + 32, key, 16);
- prov->material |= MAT_RAND_AUTH;
- if (prov->conf_inputs.start.auth_action == PROV_ACTION_IN_ALPHA) {
- msg.opcode = PROV_INP_CMPLT;
- prov_send(prov, &msg.opcode, 1);
- }
- }
- static void priv_key_cb(void *user_data, int err, uint8_t *key, uint32_t len)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- struct prov_fail_msg msg;
- if (prov != rx_prov)
- return;
- if (err || !key || len != 32) {
- msg.opcode = PROV_FAILED;
- msg.reason = PROV_ERR_UNEXPECTED_ERR;
- prov_send(prov, &msg, sizeof(msg));
- return;
- }
- /* API delivers Mesh byte order, switch to little endian */
- swap_u256_bytes(key);
- memcpy(prov->private_key, key, 32);
- ecc_make_public_key(prov->private_key,
- prov->conf_inputs.dev_pub_key);
- /* Convert Public key to Mesh byte order */
- swap_u256_bytes(prov->conf_inputs.dev_pub_key);
- swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
- prov->material |= MAT_LOCAL_PRIVATE;
- if ((prov->material & MAT_SECRET) == MAT_SECRET) {
- if (!acp_credentials(prov)) {
- msg.opcode = PROV_FAILED;
- msg.reason = PROV_ERR_UNEXPECTED_ERR;
- prov_send(prov, &msg, sizeof(msg));
- }
- }
- }
- static void send_caps(struct mesh_prov_acceptor *prov)
- {
- struct prov_caps_msg msg;
- msg.opcode = PROV_CAPS;
- memcpy(&msg.caps, &prov->conf_inputs.caps,
- sizeof(prov->conf_inputs.caps));
- prov->expected = PROV_START;
- prov_send(prov, &msg, sizeof(msg));
- }
- static void send_pub_key(struct mesh_prov_acceptor *prov)
- {
- struct prov_pub_key_msg msg;
- msg.opcode = PROV_PUB_KEY;
- memcpy(msg.pub_key, prov->conf_inputs.dev_pub_key, sizeof(msg.pub_key));
- prov_send(prov, &msg, sizeof(msg));
- }
- static bool send_conf(struct mesh_prov_acceptor *prov)
- {
- struct prov_conf_msg msg;
- msg.opcode = PROV_CONFIRM;
- mesh_crypto_aes_cmac(prov->calc_key, prov->rand_auth_workspace, 32,
- msg.conf);
- /* Fail if confirmations match */
- if (!memcmp(msg.conf, prov->confirm, sizeof(msg.conf)))
- return false;
- prov_send(prov, &msg, sizeof(msg));
- return true;
- }
- static void send_rand(struct mesh_prov_acceptor *prov)
- {
- struct prov_rand_msg msg;
- msg.opcode = PROV_RANDOM;
- memcpy(msg.rand, prov->rand_auth_workspace, sizeof(msg.rand));
- prov_send(prov, &msg, sizeof(msg));
- }
- static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- struct mesh_prov_node_info *info;
- struct prov_fail_msg fail;
- uint8_t type = *data++;
- uint32_t oob_key;
- uint64_t decode_mic;
- bool result;
- if (rx_prov != prov || !prov->trans_tx)
- return;
- l_debug("Provisioning packet received type: %2.2x (%u octets)",
- type, len);
- if (type == prov->previous) {
- l_error("Ignore repeated %2.2x packet", type);
- return;
- } else if (type > prov->expected || type < prov->previous) {
- l_error("Expected %2.2x, Got:%2.2x", prov->expected, type);
- fail.reason = PROV_ERR_UNEXPECTED_PDU;
- goto failure;
- }
- if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
- len != expected_pdu_size[type]) {
- l_error("Expected PDU size %d, Got %d (type: %2.2x)",
- len, expected_pdu_size[type], type);
- fail.reason = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
- switch (type){
- case PROV_INVITE: /* Prov Invite */
- prov->conf_inputs.invite.attention = data[0];
- send_caps(prov);
- break;
- case PROV_START: /* Prov Start */
- memcpy(&prov->conf_inputs.start, data,
- sizeof(prov->conf_inputs.start));
- if (prov->conf_inputs.start.algorithm ||
- prov->conf_inputs.start.pub_key > 1 ||
- prov->conf_inputs.start.auth_method > 3) {
- fail.reason = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
- if (prov->conf_inputs.start.pub_key) {
- if (prov->conf_inputs.caps.pub_type) {
- /* Prompt Agent for Private Key of OOB */
- mesh_agent_request_private_key(prov->agent,
- priv_key_cb, prov);
- } else {
- fail.reason = PROV_ERR_INVALID_PDU;
- goto failure;
- }
- } else {
- /* Ephemeral Public Key requested */
- ecc_make_key(prov->conf_inputs.dev_pub_key,
- prov->private_key);
- swap_u256_bytes(prov->conf_inputs.dev_pub_key);
- swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
- prov->material |= MAT_LOCAL_PRIVATE;
- }
- prov->expected = PROV_PUB_KEY;
- break;
- case PROV_PUB_KEY: /* Public Key */
- /* Save Key */
- memcpy(prov->conf_inputs.prv_pub_key, data, 64);
- prov->material |= MAT_REMOTE_PUBLIC;
- prov->expected = PROV_CONFIRM;
- if ((prov->material & MAT_SECRET) != MAT_SECRET)
- return;
- if (!acp_credentials(prov)) {
- fail.reason = PROV_ERR_UNEXPECTED_ERR;
- goto failure;
- }
- if (!prov->conf_inputs.start.pub_key)
- send_pub_key(prov);
- /* Start Step 3 */
- switch (prov->conf_inputs.start.auth_method) {
- default:
- case 0:
- /* Auth Type 3c - No OOB */
- break;
- case 1:
- /* Auth Type 3c - Static OOB */
- /* Prompt Agent for Static OOB */
- fail.reason = mesh_agent_request_static(prov->agent,
- static_cb, prov);
- if (fail.reason)
- goto failure;
- break;
- case 2:
- /* Auth Type 3a - Output OOB */
- l_getrandom(&oob_key, sizeof(oob_key));
- oob_key %= digit_mod(prov->conf_inputs.start.auth_size);
- /* Save two copies, for two confirmation values */
- l_put_be32(oob_key, prov->rand_auth_workspace + 28);
- l_put_be32(oob_key, prov->rand_auth_workspace + 44);
- prov->material |= MAT_RAND_AUTH;
- if (prov->conf_inputs.start.auth_action ==
- PROV_ACTION_OUT_ALPHA) {
- /* TODO: Construst NUL-term string to pass */
- fail.reason = mesh_agent_display_string(
- prov->agent, NULL, NULL, prov);
- } else {
- /* Ask Agent to Display U32 */
- fail.reason = mesh_agent_display_number(
- prov->agent, false,
- prov->conf_inputs.start.auth_action,
- oob_key, NULL, prov);
- }
- if (fail.reason)
- goto failure;
- break;
- case 3:
- /* Auth Type 3b - input OOB */
- /* Prompt Agent for Input OOB */
- if (prov->conf_inputs.start.auth_action ==
- PROV_ACTION_IN_ALPHA) {
- fail.reason = mesh_agent_prompt_alpha(
- prov->agent, false,
- static_cb, prov);
- } else {
- fail.reason = mesh_agent_prompt_number(
- prov->agent, false,
- prov->conf_inputs.start.auth_action,
- number_cb, prov);
- }
- if (fail.reason)
- goto failure;
- break;
- }
- prov->expected = PROV_CONFIRM;
- break;
- case PROV_CONFIRM: /* Confirmation */
- /* Save Provisioners confirmation for later compare */
- memcpy(prov->confirm, data, 16);
- prov->expected = PROV_RANDOM;
- if (!send_conf(prov)) {
- fail.reason = PROV_ERR_INVALID_PDU;
- goto failure;
- }
- break;
- case PROV_RANDOM: /* Random Value */
- /* Disallow matching random values */
- if (!memcmp(prov->rand_auth_workspace, data, 16)) {
- fail.reason = PROV_ERR_INVALID_PDU;
- goto failure;
- }
- /* Calculate Session key (needed later) while data is fresh */
- mesh_crypto_prov_prov_salt(prov->salt, data,
- prov->rand_auth_workspace,
- prov->salt);
- mesh_crypto_session_key(prov->secret, prov->salt, prov->s_key);
- mesh_crypto_nonce(prov->secret, prov->salt, prov->s_nonce);
- /* Calculate expected Provisioner Confirm */
- memcpy(prov->rand_auth_workspace + 16, data, 16);
- mesh_crypto_aes_cmac(prov->calc_key,
- prov->rand_auth_workspace + 16, 32,
- prov->calc_key);
- /* Compare our calculation with Provisioners */
- if (memcmp(prov->calc_key, prov->confirm, 16)) {
- fail.reason = PROV_ERR_CONFIRM_FAILED;
- goto failure;
- }
- /* Send Random value we used */
- send_rand(prov);
- prov->expected = PROV_DATA;
- break;
- case PROV_DATA: /* Provisioning Data */
- /* Calculate our device key */
- mesh_crypto_device_key(prov->secret,
- prov->salt,
- prov->calc_key);
- /* Decrypt new node data into workspace */
- mesh_crypto_aes_ccm_decrypt(prov->s_nonce, prov->s_key,
- NULL, 0,
- data, len - 1, prov->rand_auth_workspace,
- &decode_mic, sizeof(decode_mic));
- /* Validate that the data hasn't been messed with in transit */
- if (l_get_be64(data + 25) != decode_mic) {
- l_error("Provisioning Failed-MIC compare");
- fail.reason = PROV_ERR_DECRYPT_FAILED;
- goto failure;
- }
- info = l_malloc(sizeof(struct mesh_prov_node_info));
- memcpy(info->device_key, prov->calc_key, 16);
- memcpy(info->net_key, prov->rand_auth_workspace, 16);
- info->net_index = l_get_be16(prov->rand_auth_workspace + 16);
- info->flags = prov->rand_auth_workspace[18];
- info->iv_index = l_get_be32(prov->rand_auth_workspace + 19);
- info->unicast = l_get_be16(prov->rand_auth_workspace + 23);
- result = prov->cmplt(prov->caller_data, PROV_ERR_SUCCESS, info);
- prov->cmplt = NULL;
- l_free(info);
- if (result) {
- prov->rand_auth_workspace[0] = PROV_COMPLETE;
- prov_send(prov, prov->rand_auth_workspace, 1);
- goto cleanup;
- } else {
- fail.reason = PROV_ERR_UNEXPECTED_ERR;
- goto failure;
- }
- break;
- case PROV_FAILED: /* Provisioning Error -- abort */
- /* TODO: Call Complete Callback (Fail)*/
- prov->cmplt(prov->caller_data,
- data[0] ? data[0] : PROV_ERR_UNEXPECTED_ERR,
- NULL);
- prov->cmplt = NULL;
- goto cleanup;
- }
- if (prov)
- prov->previous = type;
- return;
- failure:
- fail.opcode = PROV_FAILED;
- prov_send(prov, &fail, sizeof(fail));
- if (prov->cmplt)
- prov->cmplt(prov->caller_data, fail.reason, NULL);
- prov->cmplt = NULL;
- cleanup:
- l_timeout_remove(prov->timeout);
- /* Give PB Link 5 seconds to end session */
- prov->timeout = l_timeout_create(5, prov_to, prov, NULL);
- }
- static void acp_prov_ack(void *user_data, uint8_t msg_num)
- {
- struct mesh_prov_acceptor *rx_prov = user_data;
- struct deferred_cmd *deferred;
- if (rx_prov != prov)
- return;
- if (prov->out_opcode == PROV_NONE)
- return;
- prov->out_opcode = PROV_NONE;
- deferred = l_queue_pop_head(prov->ob);
- if (!deferred)
- return;
- prov_send(prov, deferred->cmd, deferred->len);
- l_free(deferred);
- }
- /* This starts unprovisioned device beacon */
- bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
- uint16_t algorithms, uint32_t timeout,
- struct mesh_agent *agent,
- mesh_prov_acceptor_complete_func_t complete_cb,
- void *caller_data)
- {
- struct mesh_agent_prov_caps *caps;
- uint8_t beacon[24] = {MESH_AD_TYPE_BEACON,
- BEACON_TYPE_UNPROVISIONED};
- uint8_t len = sizeof(beacon) - sizeof(uint32_t);
- bool result;
- /* Invoked from Join() method in mesh-api.txt, to join a
- * remote mesh network.
- */
- if (prov)
- return false;
- prov = l_new(struct mesh_prov_acceptor, 1);
- prov->to_secs = timeout;
- prov->agent = agent;
- prov->cmplt = complete_cb;
- prov->ob = l_queue_new();
- prov->previous = -1;
- prov->out_opcode = PROV_NONE;
- prov->caller_data = caller_data;
- caps = mesh_agent_get_caps(agent);
- /* TODO: Should we sanity check values here or elsewhere? */
- prov->conf_inputs.caps.num_ele = num_ele;
- prov->conf_inputs.caps.pub_type = caps->pub_type;
- prov->conf_inputs.caps.static_type = caps->static_type;
- prov->conf_inputs.caps.output_size = caps->output_size;
- prov->conf_inputs.caps.input_size = caps->input_size;
- /* Store UINT16 values in Over-the-Air order, in packed structure
- * for crypto inputs
- */
- l_put_be16(algorithms, &prov->conf_inputs.caps.algorithms);
- l_put_be16(caps->output_action, &prov->conf_inputs.caps.output_action);
- l_put_be16(caps->input_action, &prov->conf_inputs.caps.input_action);
- /* Compose Unprovisioned Beacon */
- memcpy(beacon + 2, uuid, 16);
- l_put_be16(caps->oob_info, beacon + 18);
- if (caps->oob_info & OOB_INFO_URI_HASH){
- l_put_be32(caps->uri_hash, beacon + 20);
- len += sizeof(uint32_t);
- }
- /* Infinitely Beacon until Canceled, or Provisioning Starts */
- result = mesh_send_pkt(0, 500, beacon, len);
- if (!result)
- goto error_fail;
- /* Always register for PB-ADV */
- result = pb_adv_reg(false, acp_prov_open, acp_prov_close, acp_prov_rx,
- acp_prov_ack, uuid, prov);
- if (result)
- return true;
- error_fail:
- acceptor_free();
- return false;
- }
- void acceptor_cancel(void *user_data)
- {
- acceptor_free();
- }
|