This patch implements D-Bus DevKeySend() method of org.bluez.mesh.Node1 interface, allowing the application to send messages encrypted using a known remote device key. At the moment the call ignores net_index argument and sends messages using the primary subnet. Also, it's no longer possible to use 'magic' key_index value 0x7fff (denoting local device key) when calling regular Send(). Applications should use DevKeySend() instead. --- mesh/model.c | 8 ++++++- mesh/node.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/mesh/model.c b/mesh/model.c index e09dbd364..0d44ea72e 100644 --- a/mesh/model.c +++ b/mesh/model.c @@ -941,6 +941,7 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t target, const void *msg, uint16_t msg_len) { uint8_t key_id; + uint8_t dev_key[16]; const uint8_t *key; /* print_packet("Mod Tx", msg, msg_len); */ @@ -959,7 +960,12 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t target, if (!key) return false; - l_debug("(%x)", app_idx); + key_id = APP_ID_DEV; + } else if (app_idx == APP_IDX_DEV_REMOTE) { + if (!keyring_get_remote_dev_key(node, target, dev_key)) + return false; + + key = dev_key; key_id = APP_ID_DEV; } else { key = appkey_get_key(node_get_net(node), app_idx, &key_id); diff --git a/mesh/node.c b/mesh/node.c index 9acf153d9..316b889e8 100644 --- a/mesh/node.c +++ b/mesh/node.c @@ -1959,7 +1959,11 @@ static struct l_dbus_message *send_call(struct l_dbus *dbus, return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Incorrect data"); - if (!mesh_model_send(node, src, dst, app_idx, + if ((app_idx & APP_IDX_MASK) != app_idx) + return dbus_error(msg, MESH_ERROR_INVALID_ARGS, + "Invalid key_index"); + + if (!mesh_model_send(node, src, dst, app_idx & APP_IDX_MASK, mesh_net_get_default_ttl(node->net), data, len)) return dbus_error(msg, MESH_ERROR_FAILED, NULL); @@ -1969,6 +1973,53 @@ static struct l_dbus_message *send_call(struct l_dbus *dbus, return reply; } +static struct l_dbus_message *dev_key_send_call(struct l_dbus *dbus, + struct l_dbus_message *msg, + void *user_data) +{ + struct mesh_node *node = user_data; + const char *sender, *ele_path; + struct l_dbus_message_iter iter_data; + struct node_element *ele; + uint16_t dst, net_idx, src; + uint8_t *data; + uint32_t len; + struct l_dbus_message *reply; + + l_debug("DevKeySend"); + + sender = l_dbus_message_get_sender(msg); + + if (strcmp(sender, node->owner)) + return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL); + + if (!l_dbus_message_get_arguments(msg, "oqqay", &ele_path, &dst, + &net_idx, &iter_data)) + return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL); + + ele = l_queue_find(node->elements, match_element_path, ele_path); + if (!ele) + return dbus_error(msg, MESH_ERROR_NOT_FOUND, + "Element not found"); + + src = node_get_primary(node) + ele->idx; + + if (!l_dbus_message_iter_get_fixed_array(&iter_data, &data, &len) || + !len || len > MESH_MAX_ACCESS_PAYLOAD) + return dbus_error(msg, MESH_ERROR_INVALID_ARGS, + "Incorrect data"); + + /* TODO: use net_idx */ + if (!mesh_model_send(node, src, dst, APP_IDX_DEV_REMOTE, + mesh_net_get_default_ttl(node->net), data, len)) + return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL); + + reply = l_dbus_message_new_method_return(msg); + l_dbus_message_set_arguments(reply, ""); + + return reply; +} + static struct l_dbus_message *publish_call(struct l_dbus *dbus, struct l_dbus_message *msg, void *user_data) @@ -2074,7 +2125,11 @@ static void setup_node_interface(struct l_dbus_interface *iface) { l_dbus_interface_method(iface, "Send", 0, send_call, "", "oqqay", "element_path", "destination", - "key", "data"); + "key_index", "data"); + l_dbus_interface_method(iface, "DevKeySend", 0, dev_key_send_call, + "", "oqqay", "element_path", + "destination", "net_index", + "data"); l_dbus_interface_method(iface, "Publish", 0, publish_call, "", "oqay", "element_path", "model_id", "data"); l_dbus_interface_method(iface, "VendorPublish", 0, vendor_publish_call, -- 2.19.1