Bluetooth: Mesh: Fix network credential selection
The only messages that should be encrypted using the friendship credentials are those coming through the Friend Queue on the Friend node, most request-response pairs between LPN & Friend (exceptions are Friend Request - Friend Offer, and Friend Clear - Friend Clear Confirm), as well as Model Publication messages when the Friendship Credentials Flag has been enabled in the model publication. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
d43a23652c
commit
eb23d688f2
6 changed files with 36 additions and 65 deletions
|
@ -172,10 +172,7 @@ struct bt_mesh_msg_ctx {
|
|||
u16_t addr;
|
||||
|
||||
/** Received TTL value. Not used for sending. */
|
||||
u8_t recv_ttl:7;
|
||||
|
||||
/** Whether friend credentials are used. */
|
||||
u8_t friend_cred:1;
|
||||
u8_t recv_ttl;
|
||||
|
||||
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
|
||||
u8_t send_ttl;
|
||||
|
|
|
@ -437,23 +437,19 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)
|
|||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
}
|
||||
|
||||
int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *msg, bt_mesh_cb_t cb,
|
||||
void *cb_data)
|
||||
static int model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
bool friend_cred, struct net_buf_simple *msg,
|
||||
bt_mesh_cb_t cb, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(ctx->net_idx),
|
||||
.ctx = ctx,
|
||||
.src = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = friend_cred,
|
||||
};
|
||||
|
||||
if (ctx->friend_cred && !bt_mesh_lpn_established()) {
|
||||
BT_ERR("Friendship Credentials requested without a Friend");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", ctx->net_idx,
|
||||
ctx->app_idx, ctx->addr);
|
||||
BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
|
||||
|
@ -476,12 +472,22 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
|
|||
return bt_mesh_trans_send(&tx, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *msg, bt_mesh_cb_t cb,
|
||||
void *cb_data)
|
||||
{
|
||||
return model_send(model, ctx, false, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model,
|
||||
struct net_buf_simple *msg)
|
||||
{
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!model->pub) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -499,10 +505,9 @@ int bt_mesh_model_publish(struct bt_mesh_model *model,
|
|||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
ctx.addr = model->pub->addr;
|
||||
ctx.friend_cred = model->pub->cred;
|
||||
ctx.send_ttl = model->pub->ttl;
|
||||
|
||||
return bt_mesh_model_send(model, &ctx, msg, NULL, NULL);
|
||||
return model_send(model, &ctx, model->pub->cred, msg, NULL, NULL);
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
|
|
|
@ -327,13 +327,13 @@ static int send_friend_poll(void)
|
|||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = bt_mesh.lpn.frnd,
|
||||
.send_ttl = 0,
|
||||
.friend_cred = 1,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = POLL_XMIT,
|
||||
.friend_cred = true,
|
||||
};
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
u8_t fsn = lpn->fsn;
|
||||
|
@ -619,13 +619,13 @@ static bool sub_update(u8_t op)
|
|||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.addr = lpn->frnd,
|
||||
.send_ttl = 0,
|
||||
.friend_cred = 1,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = &bt_mesh.sub[0],
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_primary_addr(),
|
||||
.xmit = POLL_XMIT,
|
||||
.friend_cred = true,
|
||||
};
|
||||
struct bt_mesh_ctl_friend_sub req;
|
||||
size_t i, g;
|
||||
|
@ -928,7 +928,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
* credentials so we need to ensure the right ones (Friend
|
||||
* Credentials) were used for this message.
|
||||
*/
|
||||
if (!rx->ctx.friend_cred) {
|
||||
if (!rx->friend_cred) {
|
||||
BT_WARN("Friend Update with wrong credentials");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -670,25 +670,16 @@ do_update:
|
|||
}
|
||||
|
||||
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
|
||||
bool new_key, bool friend_cred, bt_mesh_adv_func_t cb)
|
||||
bool new_key, bt_mesh_adv_func_t cb)
|
||||
{
|
||||
const u8_t *enc, *priv;
|
||||
int err;
|
||||
|
||||
BT_DBG("net_idx 0x%04x new_key %u friend_cred %u len %u",
|
||||
sub->net_idx, new_key, friend_cred, buf->len);
|
||||
BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
|
||||
buf->len);
|
||||
|
||||
if (friend_cred) {
|
||||
err = bt_mesh_friend_cred_get(sub->net_idx,
|
||||
BT_MESH_ADDR_UNASSIGNED,
|
||||
new_key, NULL, &enc, &priv);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
enc = sub->keys[new_key].enc;
|
||||
priv = sub->keys[new_key].privacy;
|
||||
}
|
||||
enc = sub->keys[new_key].enc;
|
||||
priv = sub->keys[new_key].privacy;
|
||||
|
||||
err = bt_mesh_net_obfuscate(buf->data, BT_MESH_NET_IVI_TX, priv);
|
||||
if (err) {
|
||||
|
@ -778,20 +769,20 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
|
|||
net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->ctx->friend_cred) {
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) {
|
||||
if (bt_mesh_friend_cred_get(tx->sub->net_idx,
|
||||
BT_MESH_ADDR_UNASSIGNED,
|
||||
idx, &nid, &enc, &priv)) {
|
||||
BT_WARN("Falling back to master credentials");
|
||||
|
||||
tx->ctx->friend_cred = 0;
|
||||
tx->friend_cred = false;
|
||||
|
||||
nid = tx->sub->keys[idx].nid;
|
||||
enc = tx->sub->keys[idx].enc;
|
||||
priv = tx->sub->keys[idx].privacy;
|
||||
}
|
||||
} else {
|
||||
tx->ctx->friend_cred = 0;
|
||||
tx->friend_cred = false;
|
||||
nid = tx->sub->keys[idx].nid;
|
||||
enc = tx->sub->keys[idx].enc;
|
||||
priv = tx->sub->keys[idx].privacy;
|
||||
|
@ -1002,7 +993,7 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
|
|||
#if (defined(CONFIG_BT_MESH_LOW_POWER) || \
|
||||
defined(CONFIG_BT_MESH_FRIEND))
|
||||
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
|
||||
rx->ctx.friend_cred = 1;
|
||||
rx->friend_cred = 1;
|
||||
rx->ctx.net_idx = sub->net_idx;
|
||||
rx->sub = sub;
|
||||
return true;
|
||||
|
@ -1083,7 +1074,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
|
|||
BT_DBG("Relaying packet. TTL is now %u", TTL(buf->data));
|
||||
|
||||
/* Update NID if RX or RX was with friend credentials */
|
||||
if (rx->ctx.friend_cred) {
|
||||
if (rx->friend_cred) {
|
||||
buf->data[0] &= 0x80; /* Clear everything except IVI */
|
||||
buf->data[0] |= nid;
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ struct bt_mesh_net_rx {
|
|||
u16_t dst; /* Destination address */
|
||||
u8_t old_iv:1, /* iv_index - 1 was used */
|
||||
new_key:1, /* Data was encrypted with updated key */
|
||||
friend_cred:1, /* Data was encrypted with friend cred */
|
||||
ctl:1, /* Network Control */
|
||||
net_if:2, /* Network interface */
|
||||
local_match:1, /* Matched a local element */
|
||||
|
@ -247,6 +248,7 @@ struct bt_mesh_net_tx {
|
|||
struct bt_mesh_msg_ctx *ctx;
|
||||
u16_t src;
|
||||
u8_t xmit;
|
||||
bool friend_cred;
|
||||
};
|
||||
|
||||
extern struct bt_mesh_net bt_mesh;
|
||||
|
@ -302,7 +304,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
|
|||
bt_mesh_adv_func_t cb);
|
||||
|
||||
int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
|
||||
bool new_key, bool friend_cred, bt_mesh_adv_func_t cb);
|
||||
bool new_key, bt_mesh_adv_func_t cb);
|
||||
|
||||
int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
|
||||
struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
|
||||
|
|
|
@ -62,7 +62,6 @@ static struct seg_tx {
|
|||
u64_t seq_auth;
|
||||
u16_t dst;
|
||||
u8_t seg_n:5, /* Last segment index */
|
||||
friend_cred:1, /* Use Friendship creds */
|
||||
new_key:1; /* New/old key */
|
||||
u8_t nack_count; /* Number of unacked segs */
|
||||
bt_mesh_cb_t cb;
|
||||
|
@ -230,8 +229,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
|
|||
|
||||
BT_DBG("resending %u/%u", i, tx->seg_n);
|
||||
|
||||
err = bt_mesh_net_resend(tx->sub, seg, tx->new_key,
|
||||
tx->friend_cred, seg_sent);
|
||||
err = bt_mesh_net_resend(tx->sub, seg, tx->new_key, seg_sent);
|
||||
if (err) {
|
||||
BT_ERR("Sending segment failed");
|
||||
seg_tx_complete(tx, -EIO);
|
||||
|
@ -295,7 +293,6 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
|||
tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
|
||||
tx->sub = net_tx->sub;
|
||||
tx->new_key = net_tx->sub->kr_flag;
|
||||
tx->friend_cred = net_tx->ctx->friend_cred;
|
||||
|
||||
seq_zero = tx->seq_auth & 0x1fff;
|
||||
|
||||
|
@ -364,11 +361,6 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
|||
}
|
||||
}
|
||||
|
||||
/* bt_mesh_net_send() may have modified this if the needed
|
||||
* Friendship credentials were not found.
|
||||
*/
|
||||
tx->friend_cred = net_tx->ctx->friend_cred;
|
||||
|
||||
if (bt_mesh_lpn_established()) {
|
||||
bt_mesh_lpn_friend_poll();
|
||||
}
|
||||
|
@ -448,14 +440,6 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Communication between LPN & Friend should always be using
|
||||
* the Friendship Credentials. Any other destination should
|
||||
* use the Master Credentials.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
tx->ctx->friend_cred = bt_mesh_lpn_match(tx->ctx->addr);
|
||||
}
|
||||
|
||||
if (seg) {
|
||||
return send_seg(tx, aid, mic_len, msg, cb, cb_data);
|
||||
}
|
||||
|
@ -763,7 +747,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
|
|||
return bt_mesh_lpn_friend_clear_cfm(rx, buf);
|
||||
}
|
||||
|
||||
if (!rx->ctx.friend_cred) {
|
||||
if (!rx->friend_cred) {
|
||||
BT_WARN("Message from friend with wrong credentials");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -866,14 +850,6 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
|
|||
}
|
||||
}
|
||||
|
||||
/* Communication between LPN & Friend should always be using
|
||||
* the Friendship Credentials. Any other destination should
|
||||
* use the Master Credentials.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
tx->ctx->friend_cred = bt_mesh_lpn_match(tx->ctx->addr);
|
||||
}
|
||||
|
||||
return bt_mesh_net_send(tx, buf, cb);
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1233,7 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
|
|||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
|
||||
bt_mesh_lpn_established() &&
|
||||
(!bt_mesh_lpn_waiting_update() || !rx->ctx.friend_cred)) {
|
||||
(!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) {
|
||||
BT_WARN("Ignoring unexpected message in Low Power mode");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue