You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by na...@apache.org on 2019/07/09 08:27:13 UTC

[mynewt-nimble] branch master updated: nimble/mesh: Sync provisioning code with Zephyr

This is an automated email from the ASF dual-hosted git repository.

naraj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new 5f56107  nimble/mesh: Sync provisioning code with Zephyr
5f56107 is described below

commit 5f56107d61e7b8154342531b950f038bced9d486
Author: MichaƂ Narajowski <mi...@codecoup.pl>
AuthorDate: Mon Jul 1 12:56:37 2019 +0200

    nimble/mesh: Sync provisioning code with Zephyr
    
    This patch contains a few proposed patches from Mynewt that
    were backported to Zephyr and since there were other differences
    in this file I decided to sync it in one commit.
    
    In sync with this PR:
    https://github.com/zephyrproject-rtos/zephyr/pull/17117
---
 nimble/host/mesh/src/prov.c | 348 +++++++++++++++++++-------------------------
 1 file changed, 153 insertions(+), 195 deletions(-)

diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c
index 88475c1..791938c 100644
--- a/nimble/host/mesh/src/prov.c
+++ b/nimble/host/mesh/src/prov.c
@@ -101,13 +101,12 @@
 
 enum {
 	REMOTE_PUB_KEY,        /* Remote key has been received */
-	LOCAL_PUB_KEY,         /* Local public key is available */
 	LINK_ACTIVE,           /* Link has been opened */
-	HAVE_DHKEY,            /* DHKey has been calcualted */
+	HAVE_DHKEY,            /* DHKey has been calculated */
 	SEND_CONFIRM,          /* Waiting to send Confirm value */
 	WAIT_NUMBER,           /* Waiting for number input from user */
 	WAIT_STRING,           /* Waiting for string input from user */
-	LINK_INVALID,          /* Error occured during provisioning */
+	LINK_INVALID,          /* Error occurred during provisioning */
 
 	NUM_FLAGS,
 };
@@ -135,7 +134,6 @@ struct prov_link {
 
 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
 	u32_t id;                /* Link ID */
-#endif
 
 	struct {
 		u8_t  id;        /* Transaction ID */
@@ -159,6 +157,9 @@ struct prov_link {
 		/* Retransmit timer */
 		struct k_delayed_work retransmit;
 	} tx;
+#endif
+
+	struct k_delayed_work prot_timer;
 };
 
 struct prov_rx {
@@ -182,10 +183,56 @@ static struct os_mbuf *rx_buf;
 #define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)
 
 static struct prov_link link;
-static struct k_delayed_work prot_timer;
+
 static const struct bt_mesh_prov *prov;
 
-static void close_link(u8_t err, u8_t reason);
+static void pub_key_ready(const u8_t *pkey);
+
+static int reset_state(void)
+{
+	static struct bt_pub_key_cb pub_key_cb = {
+		.func = pub_key_ready,
+	};
+	int err;
+
+	k_delayed_work_cancel(&link.prot_timer);
+
+	/* Disable Attention Timer if it was set */
+	if (link.conf_inputs[0]) {
+		bt_mesh_attention(NULL, 0);
+	}
+
+#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
+	/* Clear everything except the retransmit and protocol timer
+	 * delayed work objects.
+	 */
+	(void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
+	link.rx.prev_id = XACT_NVAL;
+
+#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
+	link.rx.buf = bt_mesh_proxy_get_buf();
+#else
+	net_buf_simple_init(rx_buf, 0);
+	link.rx.buf = rx_buf;
+#endif /* PB_GATT */
+
+#else /* !PB_ADV */
+	/* Clear everything except the protocol timer (k_delayed_work) */
+	(void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
+#endif /* PB_ADV */
+
+#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
+	link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+#endif
+
+	err = bt_pub_key_gen(&pub_key_cb);
+	if (err) {
+		BT_ERR("Failed to generate public key (%d)", err);
+		return err;
+	}
+
+	return 0;
+}
 
 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
 static void buf_sent(int err, void *user_data)
@@ -230,40 +277,15 @@ static void prov_clear_tx(void)
 	free_segments();
 }
 
-static void reset_link(void)
+static void reset_adv_link(void)
 {
-	atomic_clear_bit(link.flags, LINK_ACTIVE);
-	atomic_clear_bit(link.flags, LINK_INVALID);
-	k_delayed_work_cancel(&prot_timer);
-
 	prov_clear_tx();
 
 	if (prov->link_close) {
 		prov->link_close(BT_MESH_PROV_ADV);
 	}
 
-	/* Clear everything except the retransmit delayed work config */
-	memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-	link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-#endif
-	link.rx.prev_id = XACT_NVAL;
-
-	if (bt_pub_key_get()) {
-		atomic_set_bit(link.flags, LOCAL_PUB_KEY);
-	}
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-	link.rx.buf = bt_mesh_proxy_get_buf();
-#else
-	net_buf_simple_init(rx_buf, 0);
-	link.rx.buf = rx_buf;
-#endif
-
-	/* Disable Attention Timer if it was set */
-	if (link.conf_inputs[0]) {
-		bt_mesh_attention(NULL, 0);
-	}
+	reset_state();
 }
 
 static struct os_mbuf *adv_buf_create(void)
@@ -469,7 +491,7 @@ static int prov_send_gatt(struct os_mbuf *msg)
 
 static inline int prov_send(struct os_mbuf *buf)
 {
-    k_delayed_work_submit(&prot_timer, PROTOCOL_TIMEOUT);
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
 
 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
 	if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
@@ -495,7 +517,13 @@ static void prov_send_fail_msg(u8_t err)
 
 	prov_buf_init(buf, PROV_FAILED);
 	net_buf_simple_add_u8(buf, err);
-	prov_send(buf);
+
+	if (prov_send(buf)) {
+		BT_ERR("Failed to send Provisioning Failed message");
+	}
+
+	atomic_set_bit(link.flags, LINK_INVALID);
+
 	os_mbuf_free_chain(buf);
 }
 
@@ -503,7 +531,7 @@ static void prov_invite(const u8_t *data)
 {
 	struct os_mbuf *buf = PROV_BUF(12);
 
-	BT_INFO("Attention Duration: %u seconds", data[0]);
+	BT_DBG("Attention Duration: %u seconds", data[0]);
 
 	if (data[0]) {
 		bt_mesh_attention(NULL, data[0]);
@@ -519,8 +547,7 @@ static void prov_invite(const u8_t *data)
 	/* Supported algorithms - FIPS P-256 Eliptic Curve */
 	net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
 
-	/* Public Key Type */
-	/* Only No OOB Public Key is supported*/
+	/* Public Key Type, Only "No OOB" Public Key is supported*/
 	net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
 
 	/* Static OOB Type */
@@ -542,8 +569,6 @@ static void prov_invite(const u8_t *data)
 
 	if (prov_send(buf)) {
 		BT_ERR("Failed to send capabilities");
-		prov_send_fail_msg(PROV_ERR_RESOURCES);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -557,22 +582,22 @@ static void prov_capabilities(const u8_t *data)
 {
 	u16_t algorithms, output_action, input_action;
 
-	BT_INFO("Elements: %u", data[0]);
+	BT_DBG("Elements: %u", data[0]);
 
 	algorithms = sys_get_be16(&data[1]);
-	BT_INFO("Algorithms:        %u", algorithms);
+	BT_DBG("Algorithms:        %u", algorithms);
 
-	BT_INFO("Public Key Type:   0x%02x", data[3]);
-	BT_INFO("Static OOB Type:   0x%02x", data[4]);
-	BT_INFO("Output OOB Size:   %u", data[5]);
+	BT_DBG("Public Key Type:   0x%02x", data[3]);
+	BT_DBG("Static OOB Type:   0x%02x", data[4]);
+	BT_DBG("Output OOB Size:   %u", data[5]);
 
 	output_action = sys_get_be16(&data[6]);
-	BT_INFO("Output OOB Action: 0x%04x", output_action);
+	BT_DBG("Output OOB Action: 0x%04x", output_action);
 
-	BT_INFO("Input OOB Size:    %u", data[8]);
+	BT_DBG("Input OOB Size:    %u", data[8]);
 
 	input_action = sys_get_be16(&data[9]);
-	BT_INFO("Input OOB Action:  0x%04x", input_action);
+	BT_DBG("Input OOB Action:  0x%04x", input_action);
 }
 
 static bt_mesh_output_action_t output_action(u8_t action)
@@ -710,23 +735,21 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
 
 static void prov_start(const u8_t *data)
 {
-	BT_INFO("Algorithm:   0x%02x", data[0]);
-	BT_INFO("Public Key:  0x%02x", data[1]);
-	BT_INFO("Auth Method: 0x%02x", data[2]);
-	BT_INFO("Auth Action: 0x%02x", data[3]);
-	BT_INFO("Auth Size:   0x%02x", data[4]);
+	BT_DBG("Algorithm:   0x%02x", data[0]);
+	BT_DBG("Public Key:  0x%02x", data[1]);
+	BT_DBG("Auth Method: 0x%02x", data[2]);
+	BT_DBG("Auth Action: 0x%02x", data[3]);
+	BT_DBG("Auth Size:   0x%02x", data[4]);
 
 	if (data[0] != PROV_ALG_P256) {
 		BT_ERR("Unknown algorithm 0x%02x", data[0]);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
 	if (data[1] != PUB_KEY_NO_OOB) {
-		BT_ERR("Invalid public key value: 0x%02x", data[1]);
+		BT_ERR("Invalid public key type: 0x%02x", data[1]);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -740,7 +763,6 @@ static void prov_start(const u8_t *data)
 			"action: 0x%02x; size: 0x%02x", data[2], data[3],
 			data[4]);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 	}
 }
 
@@ -755,7 +777,6 @@ static void send_confirm(void)
 	if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
 		BT_ERR("Unable to generate confirmation salt");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -764,7 +785,6 @@ static void send_confirm(void)
 	if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
 		BT_ERR("Unable to generate confirmation key");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -773,7 +793,6 @@ static void send_confirm(void)
 	if (bt_rand(link.rand, 16)) {
 		BT_ERR("Unable to generate random number");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -785,14 +804,11 @@ static void send_confirm(void)
 			      net_buf_simple_add(cfm, 16))) {
 		BT_ERR("Unable to generate confirmation value");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
 	if (prov_send(cfm)) {
 		BT_ERR("Failed to send Provisioning Confirm");
-		prov_send_fail_msg(PROV_ERR_RESOURCES);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -807,7 +823,9 @@ static void send_input_complete(void)
 	struct os_mbuf *buf = PROV_BUF(1);
 
 	prov_buf_init(buf, PROV_INPUT_COMPLETE);
-	prov_send(buf);
+	if (prov_send(buf)) {
+		BT_ERR("Failed to send Provisioning Input Complete");
+	}
 
 	os_mbuf_free_chain(buf);
 }
@@ -865,7 +883,6 @@ static void prov_dh_key_cb(const u8_t key[32])
 	if (!key) {
 		BT_ERR("DHKey generation failed");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -893,35 +910,37 @@ static void send_pub_key(void)
 	key = bt_pub_key_get();
 	if (!key) {
 		BT_ERR("No public key available");
-		prov_send_fail_msg(PROV_ERR_RESOURCES);
-		atomic_set_bit(link.flags, LINK_INVALID);
+		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
 		goto done;
 	}
 
-	prov_buf_init(buf, PROV_PUB_KEY);
-
-	/* Swap X and Y halves independently to big-endian */
-	sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
-	sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
-
-	memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
-
-	BT_DBG("Local Public Key: %s", bt_hex(&buf->om_data[1], 64));
-
-	prov_send(buf);
+	BT_DBG("Local Public Key: %s", bt_hex(key, 64));
 
 	/* Copy remote key in little-endian for bt_dh_key_gen().
-	 * X and Y halves are swapped independently.
+	 * X and Y halves are swapped independently. Use response
+	 * buffer as a temporary storage location. The bt_dh_key_gen()
+	 * will also take care of validating the remote public key.
 	 */
-	net_buf_simple_init(buf, 0);
 	sys_memcpy_swap(buf->om_data, &link.conf_inputs[17], 32);
 	sys_memcpy_swap(&buf->om_data[32], &link.conf_inputs[49], 32);
 
 	if (bt_dh_key_gen(buf->om_data, prov_dh_key_cb)) {
 		BT_ERR("Failed to generate DHKey");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
-		goto done;
+		return;
+	}
+
+	prov_buf_init(buf, PROV_PUB_KEY);
+
+	/* Swap X and Y halves independently to big-endian */
+	sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
+	sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
+
+	memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
+
+	if (prov_send(buf)) {
+		BT_ERR("Failed to send Public Key");
+		return;
 	}
 
 	link.expect = PROV_CONFIRM;
@@ -932,11 +951,11 @@ done:
 
 static void prov_pub_key(const u8_t *data)
 {
-	BT_INFO("Remote Public Key: %s", bt_hex(data, 64));
+	BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
 
 	memcpy(&link.conf_inputs[17], data, 64);
 
-	if (!atomic_test_bit(link.flags, LOCAL_PUB_KEY)) {
+	if (!bt_pub_key_get()) {
 		/* Clear retransmit timer */
 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
 		prov_clear_tx();
@@ -958,8 +977,6 @@ static void pub_key_ready(const u8_t *pkey)
 
 	BT_DBG("Local public key ready");
 
-	atomic_set_bit(link.flags, LOCAL_PUB_KEY);
-
 	if (atomic_test_and_clear_bit(link.flags, REMOTE_PUB_KEY)) {
 		send_pub_key();
 	}
@@ -972,7 +989,7 @@ static void prov_input_complete(const u8_t *data)
 
 static void prov_confirm(const u8_t *data)
 {
-	BT_INFO("Remote Confirm: %s", bt_hex(data, 16));
+	BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
 
 	memcpy(link.conf, data, 16);
 
@@ -991,12 +1008,11 @@ static void prov_random(const u8_t *data)
 	struct os_mbuf *rnd = PROV_BUF(16);
 	u8_t conf_verify[16];
 
-	BT_INFO("Remote Random: %s", bt_hex(data, 16));
+	BT_DBG("Remote Random: %s", bt_hex(data, 16));
 
 	if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
 		BT_ERR("Unable to calculate confirmation verification");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1005,7 +1021,6 @@ static void prov_random(const u8_t *data)
 		BT_DBG("Received:   %s", bt_hex(link.conf, 16));
 		BT_DBG("Calculated: %s",  bt_hex(conf_verify, 16));
 		prov_send_fail_msg(PROV_ERR_CFM_FAILED);
-		atomic_set_bit(link.flags ,LINK_INVALID);
 		goto done;
 	}
 
@@ -1014,8 +1029,6 @@ static void prov_random(const u8_t *data)
 
 	if (prov_send(rnd)) {
 		BT_ERR("Failed to send Provisioning Random");
-		prov_send_fail_msg(PROV_ERR_RESOURCES);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1023,7 +1036,6 @@ static void prov_random(const u8_t *data)
 			      link.prov_salt)) {
 		BT_ERR("Failed to generate provisioning salt");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1064,7 +1076,6 @@ static void prov_data(const u8_t *data)
 	if (err) {
 		BT_ERR("Unable to generate session key");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1074,7 +1085,6 @@ static void prov_data(const u8_t *data)
 	if (err) {
 		BT_ERR("Unable to generate session nonce");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1084,7 +1094,6 @@ static void prov_data(const u8_t *data)
 	if (err) {
 		BT_ERR("Unable to decrypt provisioning data");
 		prov_send_fail_msg(PROV_ERR_DECRYPT);
-		atomic_set_bit(link.flags ,LINK_INVALID);
 		goto done;
 	}
 
@@ -1092,7 +1101,6 @@ static void prov_data(const u8_t *data)
 	if (err) {
 		BT_ERR("Unable to generate device key");
 		prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		goto done;
 	}
 
@@ -1107,7 +1115,10 @@ static void prov_data(const u8_t *data)
 	       net_idx, (unsigned) iv_index, addr);
 
 	prov_buf_init(msg, PROV_COMPLETE);
-	prov_send(msg);
+	if (prov_send(msg)) {
+		BT_ERR("Failed to send Provisioning Complete");
+		goto done;
+	}
 
 	/* Ignore any further PDUs on this link */
 	link.expect = 0;
@@ -1119,7 +1130,11 @@ static void prov_data(const u8_t *data)
 		identity_enable = false;
 	}
 
-	bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+	err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+	if (err) {
+		BT_ERR("Failed to provision (err %d)", err);
+		goto done;
+	}
 
 	/* After PB-GATT provisioning we should start advertising
 	 * using Node Identity.
@@ -1134,7 +1149,7 @@ done:
 
 static void prov_complete(const u8_t *data)
 {
-	BT_INFO("");
+	BT_DBG("");
 }
 
 static void prov_failed(const u8_t *data)
@@ -1158,32 +1173,6 @@ static const struct {
 	{ prov_failed, 1 },
 };
 
-static void close_link(u8_t err, u8_t reason)
-{
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-	if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
-		bt_mesh_pb_gatt_close(link.conn_handle);
-		return;
-	}
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-	if (err) {
-		prov_send_fail_msg(err);
-	}
-
-	link.rx.seg = 0;
-	bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
-#endif
-
-	atomic_clear_bit(link.flags, LINK_ACTIVE);
-
-	/* Disable Attention Timer if it was set */
-	if (link.conf_inputs[0]) {
-		bt_mesh_attention(NULL, 0);
-	}
-}
-
 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
 static void prov_retransmit(struct ble_npl_event *work)
 {
@@ -1198,7 +1187,7 @@ static void prov_retransmit(struct ble_npl_event *work)
 
 	if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) {
 		BT_WARN("Giving up transaction");
-		reset_link();
+		reset_adv_link();
 		return;
 	}
 
@@ -1224,15 +1213,9 @@ static void prov_retransmit(struct ble_npl_event *work)
 	}
 }
 
-static void prot_tmo_link_close(struct ble_npl_event *ev)
-{
-    close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
-    reset_link();
-}
-
 static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
 {
-	BT_INFO("link open: len %u", buf->om_len);
+	BT_DBG("link open: len %u", buf->om_len);
 
 	if (buf->om_len < 16) {
 		BT_ERR("Too short bearer open message (len %u)", buf->om_len);
@@ -1272,14 +1255,14 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
 
 static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
 {
-	BT_INFO("Link ack: len %u", buf->om_len);
+	BT_DBG("Link ack: len %u", buf->om_len);
 }
 
 static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
 {
-	BT_INFO("Link close: len %u", buf->om_len);
+	BT_DBG("Link close: len %u", buf->om_len);
 
-	reset_link();
+	reset_adv_link();
 }
 
 static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
@@ -1317,11 +1300,12 @@ static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
 
 static void prov_msg_recv(void)
 {
-	k_delayed_work_submit(&prot_timer, PROTOCOL_TIMEOUT);
 	u8_t type = link.rx.buf->om_data[0];
 
 	BT_DBG("type 0x%02x len %u", type, link.rx.buf->om_len);
 
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
 	if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
 		BT_ERR("Incorrect FCS");
 		return;
@@ -1332,7 +1316,7 @@ static void prov_msg_recv(void)
 	link.rx.id = 0;
 
 	if (atomic_test_bit(link.flags, LINK_INVALID)) {
-		BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
+		BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
 		prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
 		return;
 	}
@@ -1340,14 +1324,12 @@ static void prov_msg_recv(void)
 	if (type != PROV_FAILED && type != link.expect) {
 		BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
 		prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
 	if (type >= ARRAY_SIZE(prov_handlers)) {
 		BT_ERR("Unknown provisioning PDU type 0x%02x", type);
 		prov_send_fail_msg(PROV_ERR_NVAL_PDU);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -1355,7 +1337,6 @@ static void prov_msg_recv(void)
 		BT_ERR("Invalid length %u for type 0x%02x",
 		       link.rx.buf->om_len, type);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -1383,18 +1364,16 @@ static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
 	if (seg > link.rx.last_seg) {
 		BT_ERR("Invalid segment index %u", seg);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	} else if (seg == link.rx.last_seg) {
 		u8_t expect_len;
 
 		expect_len = (link.rx.buf->om_len - 20 -
-			      (23 * (link.rx.last_seg - 1)));
+			      ((link.rx.last_seg - 1) * 23));
 		if (expect_len != buf->om_len) {
 			BT_ERR("Incorrect last seg len: %u != %u",
 			       expect_len, buf->om_len);
 			prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-			atomic_set_bit(link.flags, LINK_INVALID);
 			return;
 		}
 	}
@@ -1452,7 +1431,6 @@ static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
 	if (link.rx.buf->om_len < 1) {
 		BT_ERR("Ignoring zero-length provisioning PDU");
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -1460,14 +1438,12 @@ static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
 		BT_ERR("Too large provisioning PDU (%u bytes)",
 		       link.rx.buf->om_len);
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
 	if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20) {
 		BT_ERR("Too small total length for multi-segment PDU");
 		prov_send_fail_msg(PROV_ERR_NVAL_FMT);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return;
 	}
 
@@ -1505,7 +1481,7 @@ static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
 		return;
 	}
 
-	BT_INFO("prov_action: %d", GPCF(rx->gpc));
+	BT_DBG("prov_action: %d", GPCF(rx->gpc));
 	gen_prov[GPCF(rx->gpc)].func(rx, buf);
 }
 
@@ -1559,7 +1535,6 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
 	if (type != PROV_FAILED && type != link.expect) {
 		BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
 		prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
-		atomic_set_bit(link.flags, LINK_INVALID);
 		return -EINVAL;
 	}
 
@@ -1599,8 +1574,6 @@ int bt_mesh_pb_gatt_open(uint16_t conn_handle)
 
 int bt_mesh_pb_gatt_close(uint16_t conn_handle)
 {
-	bool pub_key;
-
 	BT_DBG("conn_handle %d", conn_handle);
 
 	if (link.conn_handle != conn_handle) {
@@ -1608,23 +1581,11 @@ int bt_mesh_pb_gatt_close(uint16_t conn_handle)
 		return -ENOTCONN;
 	}
 
-	/* Disable Attention Timer if it was set */
-	if (link.conf_inputs[0]) {
-		bt_mesh_attention(NULL, 0);
-	}
-
 	if (prov->link_close) {
 		prov->link_close(BT_MESH_PROV_GATT);
 	}
 
-	pub_key = atomic_test_bit(link.flags, LOCAL_PUB_KEY);
-	memset(&link, 0, sizeof(link));
-
-	if (pub_key) {
-		atomic_set_bit(link.flags, LOCAL_PUB_KEY);
-	}
-
-	return 0;
+	return reset_state();
 }
 #endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
 
@@ -1638,57 +1599,54 @@ bool bt_prov_active(void)
 	return atomic_test_bit(link.flags, LINK_ACTIVE);
 }
 
-int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
+static void protocol_timeout(struct ble_npl_event *work)
 {
-	k_delayed_work_init(&prot_timer, prot_tmo_link_close);
-	static struct bt_pub_key_cb pub_key_cb = {
-		.func = pub_key_ready,
-	};
-	int err;
+	BT_DBG("Protocol timeout");
 
-#if !(MYNEWT_VAL(BLE_MESH_PB_GATT))
-	rx_buf = NET_BUF_SIMPLE(65);
+#if MYNEWT_VAL(BLE_MESH_PB_GATT)
+	if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
+		bt_mesh_pb_gatt_close(link.conn_handle);
+		return;
+	}
 #endif
 
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-	link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+#if MYNEWT_VAL(BLE_MESH_PB_ADV)
+	u8_t reason = CLOSE_REASON_TIMEOUT;
+
+	link.rx.seg = 0U;
+	bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
+
+	reset_state();
 #endif
+}
 
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
+{
 	if (!prov_info) {
 		BT_ERR("No provisioning context provided");
 		return -EINVAL;
 	}
 
-	err = bt_pub_key_gen(&pub_key_cb);
-	if (err) {
-		BT_ERR("Failed to generate public key (%d)", err);
-		return err;
-	}
+	k_delayed_work_init(&link.prot_timer, protocol_timeout);
 
 	prov = prov_info;
 
-	(void)prov_handlers;
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
+#if MYNEWT_VAL(BLE_MESH_PB_ADV)
 	k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
-	link.rx.prev_id = XACT_NVAL;
-
-#if !(MYNEWT_VAL(BLE_MESH_PB_GATT))
-	net_buf_simple_init(rx_buf, 0);
-	link.rx.buf = rx_buf;
 #endif
 
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-	return 0;
+	return reset_state();
 }
 
-void bt_mesh_prov_reset_link(void) {
+void bt_mesh_prov_reset_link(void)
+{
+#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-    link.rx.buf = bt_mesh_proxy_get_buf();
+	link.rx.buf = bt_mesh_proxy_get_buf();
 #else
-    net_buf_simple_init(rx_buf, 0);
-    link.rx.buf = rx_buf;
+	net_buf_simple_init(rx_buf, 0);
+	link.rx.buf = rx_buf;
+#endif
 #endif
 }