All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Gix <brian.gix@intel.com>
To: linux-bluetooth@vger.kernel.org
Cc: johan.hedberg@gmail.com, inga.stotland@intel.com,
	marcel@holtmann.org, brian.gix@intel.com
Subject: [PATCH BlueZ v3 09/30] mesh: Acceptor side provisioning implimentation
Date: Fri, 14 Dec 2018 16:26:03 -0800	[thread overview]
Message-ID: <20181215002624.9313-10-brian.gix@intel.com> (raw)
In-Reply-To: <20181215002624.9313-1-brian.gix@intel.com>

---
 mesh/prov-acceptor.c | 711 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 711 insertions(+)
 create mode 100644 mesh/prov-acceptor.c

diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c
new file mode 100644
index 000000000..ac42e1e2c
--- /dev/null
+++ b/mesh/prov-acceptor.c
@@ -0,0 +1,711 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2018  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <time.h>
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+#include "src/shared/ecc.h"
+
+#include "mesh/util.h"
+#include "mesh/net_keys.h"
+#include "mesh/crypto.h"
+#include "mesh/net.h"
+#include "mesh/error.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
+
+static const uint8_t pkt_filter = MESH_AD_TYPE_PROVISION;
+static const uint8_t bec_filter[] = {MESH_AD_TYPE_BEACON,
+						BEACON_TYPE_UNPROVISIONED};
+
+enum acp_state {
+	ACP_PROV_IDLE = 0,
+	ACP_PROV_CAPS_SENT,
+	ACP_PROV_CAPS_ACKED,
+	ACP_PROV_KEY_SENT,
+	ACP_PROV_KEY_ACKED,
+	ACP_PROV_INP_CMPLT_SENT,
+	ACP_PROV_INP_CMPLT_ACKED,
+	ACP_PROV_CONF_SENT,
+	ACP_PROV_CONF_ACKED,
+	ACP_PROV_RAND_SENT,
+	ACP_PROV_RAND_ACKED,
+	ACP_PROV_CMPLT_SENT,
+	ACP_PROV_FAIL_SENT,
+};
+
+#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;
+	void *agent;
+	void *caller_data;
+	void *trans_data;
+	struct l_timeout *timeout;
+	uint32_t to_secs;
+	enum acp_state	state;
+	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)
+		l_timeout_remove(prov->timeout);
+
+	mesh_send_cancel(bec_filter, sizeof(bec_filter));
+	mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
+
+	if (prov->trans_tx) {
+		if (prov->transport == PB_ADV)
+			pb_adv_unreg(prov->trans_data);
+#if defined(GATT_ENABLED)
+		/* TODO: Cleanup GATT bearer if exists */
+		else if (prov->transport == PB_GATT)
+			pb_gatt_unreg(prov->trans_data);
+#endif
+	}
+
+	l_free(prov);
+	prov = NULL;
+}
+
+static void acp_prov_close(void *user_data, uint8_t reason)
+{
+	/* TODO: Handle Close */
+}
+
+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;
+
+	prov->timeout = NULL;
+
+	if (prov->cmplt && prov->trans_tx) {
+		prov->cmplt(prov->caller_data, PROV_ERR_TIMEOUT, NULL);
+		prov->cmplt = NULL;
+		prov->trans_tx(prov->trans_data, 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) {
+#if defined(GATT_ENABLED)
+		/* TODO: Disable PB-GATT */
+#endif
+	}
+
+#if defined(GATT_ENABLED)
+	else if (transport == PB_GATT) {
+		/* TODO: Disable PB-ADV */
+		pb_adv_unreg(prov);
+	}
+#endif
+
+	else
+		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 void 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);
+
+	ecdh_shared_secret(tmp, priv, secret);
+
+	/* Convert to Mesh byte order */
+	swap_u256_bytes(secret);
+}
+
+static void acp_credentials(struct mesh_prov_acceptor *prov)
+{
+	prov_calc_secret(prov->conf_inputs.prv_pub_key,
+			prov->private_key, prov->secret);
+
+	mesh_crypto_s1(&prov->conf_inputs,
+			sizeof(prov->conf_inputs), prov->salt);
+
+	mesh_crypto_prov_conf_key(prov->secret, prov->salt,
+			prov->calc_key);
+
+	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);
+	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);
+}
+
+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, mesh_error_t err, uint32_t number)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		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;
+	out[0] = PROV_INP_CMPLT;
+	prov->trans_tx(prov->trans_data, out, 1);
+}
+
+static void static_cb(void *user_data, mesh_error_t err,
+						uint8_t *key, uint32_t len)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err || !key || len != 16) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		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;
+}
+
+static void priv_key_cb(void *user_data, mesh_error_t err,
+						uint8_t *key, uint32_t len)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err || !key || len != 32) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		return;
+	}
+
+	memcpy(prov->private_key, key, 32);
+	ecc_make_public_key(prov->private_key,
+			prov->conf_inputs.dev_pub_key);
+
+	/* Convert 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)
+		acp_credentials(prov);
+}
+
+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;
+	uint8_t *out;
+	uint8_t type = *data++;
+	uint8_t fail_code[2];
+	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_code[1] = 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_code[1] = PROV_ERR_INVALID_FORMAT;
+		goto failure;
+	}
+
+	switch (type){
+	case PROV_INVITE: /* Prov Invite */
+		/* Prov Capabilities */
+		out = l_malloc(1 + sizeof(struct mesh_net_prov_caps));
+		out[0] = PROV_CAPS;
+		memcpy(out + 1, &prov->conf_inputs.caps,
+					sizeof(prov->conf_inputs.caps));
+
+		prov->conf_inputs.invite.attention = data[0];
+
+		prov->state = ACP_PROV_CAPS_SENT;
+		prov->expected = PROV_START;
+		prov->trans_tx(prov->trans_data,
+				out, sizeof(prov->conf_inputs.caps) + 1);
+		l_free(out);
+		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_code[1] = 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_code[1] = 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;
+
+		acp_credentials(prov);
+
+		if (!prov->conf_inputs.start.pub_key) {
+			out = l_malloc(65);
+			out[0] = PROV_PUB_KEY;
+			memcpy(out + 1, prov->conf_inputs.dev_pub_key, 64);
+			prov->trans_tx(prov->trans_data, out, 65);
+			l_free(out);
+		}
+
+		/* 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_code[1] = mesh_agent_request_static(prov->agent,
+					static_cb, prov);
+
+			if (fail_code[1])
+				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_code[1] = mesh_agent_display_string(
+					prov->agent, NULL, NULL, prov);
+			} else {
+				/* Ask Agent to Display U32 */
+				fail_code[1] = mesh_agent_display_number(
+					prov->agent, false,
+					prov->conf_inputs.start.auth_action,
+					oob_key, NULL, prov);
+			}
+
+			if (fail_code[1])
+				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_code[1] = mesh_agent_prompt_alpha(
+					prov->agent,
+					static_cb, prov);
+			} else {
+				fail_code[1] = mesh_agent_prompt_number(
+					prov->agent, false,
+					prov->conf_inputs.start.auth_action,
+					number_cb, prov);
+			}
+
+			if (fail_code[1])
+				goto failure;
+
+			break;
+		}
+
+		prov->expected = PROV_CONFIRM;
+		break;
+
+	case PROV_CONFIRM: /* Confirmation */
+		out = l_malloc(17);
+		out[0] = PROV_CONFIRM;
+
+		/* Calculate and Send our Confirmation */
+		mesh_crypto_aes_cmac(prov->calc_key, prov->rand_auth_workspace,
+								32, out + 1);
+		prov->trans_tx(prov->trans_data, out, 17);
+		l_free(out);
+
+		/* Save Provisioners confirmation for later compare */
+		memcpy(prov->confirm, data, 16);
+		prov->expected = PROV_RANDOM;
+		break;
+
+	case PROV_RANDOM: /* Random Value */
+		out = l_malloc(17);
+		/* 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, out);
+
+		/* Compare our calculation with Provisioners */
+		if (memcmp(out, prov->confirm, 16)) {
+			fail_code[1] = PROV_ERR_CONFIRM_FAILED;
+			l_free(out);
+			goto failure;
+		}
+
+		/* Send Random value we used */
+		out[0] = PROV_RANDOM;
+		memcpy(out + 1, prov->rand_auth_workspace, 16);
+		prov->trans_tx(prov->trans_data, out, 17);
+		l_free(out);
+		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_code[1] = 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->trans_tx(prov->trans_data,
+					prov->rand_auth_workspace, 1);
+			goto cleanup;
+		} else {
+			fail_code[1] = 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;
+	}
+
+	prov->previous = type;
+	return;
+
+failure:
+	fail_code[0] = PROV_FAILED;
+	prov->trans_tx(prov->trans_data, fail_code, 2);
+	if (prov->cmplt)
+		prov->cmplt(prov->caller_data, fail_code[1], 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)
+{
+	/* TODO: Handle PB-ADV Ack */
+}
+
+
+/* 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 defined(GATT_ENABLED)
+	/* If we support PB-GATT, that means we need to set up a GATT
+	 * service, and need the existence of bluetoothd, with it's
+	 * own LE capable controller. That is a battle for another day.
+	 * We will *always* support PB-ADV.
+	 */
+#endif
+	if (prov)
+		return false;
+
+	prov = l_new(struct mesh_prov_acceptor, 1);
+	prov->to_secs = timeout;
+	prov->agent = agent;
+	prov->cmplt = complete_cb;
+	prov->previous = -1;
+	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(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();
+}
-- 
2.14.5


  parent reply	other threads:[~2018-12-15  0:26 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-15  0:25 [PATCH BlueZ v3 00/30] Major rewrite for Multi-Node and DBus Brian Gix
2018-12-15  0:25 ` [PATCH BlueZ v3 01/30] mesh: Staging for Mesh DBus API rewrite Brian Gix
2018-12-15  0:25 ` [PATCH BlueZ v3 02/30] mesh: Delete obsolete files Brian Gix
2018-12-15  0:25 ` [PATCH BlueZ v3 03/30] mesh: Utilities for DBus support Brian Gix
2018-12-15  0:25 ` [PATCH BlueZ v3 04/30] mesh: Internal errors Brian Gix
2018-12-15  0:25 ` [PATCH BlueZ v3 05/30] mesh: Re-write storage for Multiple Nodes Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 06/30] mesh: Rewrite Node handling for multiple nodes Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 07/30] mesh: Rewite Network layer " Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 08/30] mesh: Direction agnostic PB-Adv implimentation Brian Gix
2018-12-15  0:26 ` Brian Gix [this message]
2018-12-15  0:26 ` [PATCH BlueZ v3 10/30] mesh: Initiator side provisioning implimentation Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 11/30] mesh: Rewrite Controler interface for full init Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 12/30] mesh: Unchanged variables set to const Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 13/30] mesh: centralize generic utilities Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 14/30] mesh: re-arrange provisioning for DBus API Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 15/30] mesh: Re-architect " Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 16/30] mesh: Make config model handle multiple nodes Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 17/30] mesh: Multi node Config Server model Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 18/30] mesh: restructure I/O for multiple nodes Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 19/30] mesh: Restrusture DB to support " Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 20/30] mesh: restructure model services for " Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 21/30] mesh: DBUS interface for Provisioning Agent Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 22/30] mesh: restructure App Key storage Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 23/30] mesh: Clean-up Comment style Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 24/30] mesh: Update for DBus API and multi-node support Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 25/30] mesh: Add default location for Mesh Node storage Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 26/30] mesh: Add structural changes for mesh Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 27/30] mesh: Sample Provisioning Agent Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 28/30] mesh: Sample On/Off Client and Server Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 29/30] mesh: Sample Mesh Joiner (provision acceptor) Brian Gix
2018-12-15  0:26 ` [PATCH BlueZ v3 30/30] mesh: Enable building Mesh Daemon Brian Gix
2018-12-17 18:42 ` [PATCH BlueZ v3 00/30] Major rewrite for Multi-Node and DBus Gix, Brian
2018-12-18  8:16   ` Szymon Janc
2018-12-18  9:14     ` Szymon Janc
2018-12-18 13:47       ` Marcel Holtmann
2018-12-18 15:08     ` Gix, Brian
2018-12-18 16:26       ` Marcel Holtmann
2018-12-18 16:50         ` Gix, Brian
2018-12-18 17:12           ` Marcel Holtmann
2018-12-19 13:02       ` Szymon Janc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181215002624.9313-10-brian.gix@intel.com \
    --to=brian.gix@intel.com \
    --cc=inga.stotland@intel.com \
    --cc=johan.hedberg@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=marcel@holtmann.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.