mesh: Add key storage
authorBrian Gix <brian.gix@intel.com>
Thu, 9 May 2019 21:33:21 +0000 (14:33 -0700)
committerAnupam Roy <anupam.r@samsung.com>
Tue, 17 Dec 2019 14:27:01 +0000 (19:57 +0530)
This implements internal key storage add/delete/fetch for the three
basic key types managed in Mesh: Network, Application and Device.

This key storage is separate from keys assigned to nodes within the
mesh, and are used to support Configuration Client functionality.

Change-Id: Ie582b6c0de2ed81c3b9e35cd5f1fc63674be2334
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
Makefile.mesh
mesh/keyring.c [new file with mode: 0644]
mesh/keyring.h [new file with mode: 0644]

index bc14721..eaaff20 100644 (file)
@@ -25,6 +25,7 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \
                                mesh/agent.h mesh/agent.c \
                                mesh/prov-acceptor.c mesh/prov-initiator.c \
                                mesh/pb-adv.h mesh/pb-adv.c \
+                               mesh/keyring.h mesh/keyring.c \
                                mesh/mesh-defs.h
 libexec_PROGRAMS += mesh/bluetooth-meshd
 
diff --git a/mesh/keyring.c b/mesh/keyring.c
new file mode 100644 (file)
index 0000000..59aa1ea
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2019  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
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libgen.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+
+#include "mesh/net.h"
+#include "mesh/keyring.h"
+#include "mesh/mesh.h"
+#include "mesh/node.h"
+
+const char *dev_key_dir = "/dev_keys";
+const char *app_key_dir = "/app_keys";
+const char *net_key_dir = "/net_keys";
+
+bool keyring_put_net_key(struct mesh_node *node, uint16_t net_idx,
+                                               struct keyring_net_key *key)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = false;
+       int fd;
+
+       if (!node || !key)
+               return false;
+
+       node_path = node_path_get(node);
+
+       if (strlen(node_path) + strlen(net_key_dir) + 1 + 3 >= PATH_MAX)
+               return false;
+
+       snprintf(key_file, PATH_MAX, "%s%s", node_path, net_key_dir);
+       mkdir(key_file, 0755);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir,
+                                                               net_idx);
+       l_debug("Put Net Key %s", key_file);
+
+       fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC);
+       if (fd >= 0) {
+               if (write(fd, key, sizeof(*key)) == sizeof(*key))
+                       result = true;
+
+               close(fd);
+       }
+
+       return result;
+}
+
+bool keyring_put_app_key(struct mesh_node *node, uint16_t app_idx,
+                               uint16_t net_idx, struct keyring_app_key *key)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = false;
+       int fd;
+
+       if (!node || !key)
+               return false;
+
+       node_path = node_path_get(node);
+
+       if (strlen(node_path) + strlen(app_key_dir) + 1 + 3 >= PATH_MAX)
+               return false;
+
+       snprintf(key_file, PATH_MAX, "%s%s", node_path, app_key_dir);
+       mkdir(key_file, 0755);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir,
+                                                               app_idx);
+       l_debug("Put App Key %s", key_file);
+
+       fd = open(key_file, O_RDWR);
+       if (fd >= 0) {
+               struct keyring_app_key old_key;
+
+               if (read(fd, &old_key, sizeof(old_key)) == sizeof(old_key)) {
+                       if (old_key.net_idx != net_idx) {
+                               close(fd);
+                               return false;
+                       }
+               }
+               lseek(fd, 0, SEEK_SET);
+       } else
+               fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC);
+
+       if (fd >= 0) {
+               if (write(fd, key, sizeof(*key)) == sizeof(*key))
+                       result = true;
+
+               close(fd);
+       }
+
+       return result;
+}
+
+bool keyring_put_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                       uint8_t count, uint8_t dev_key[16])
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = true;
+       int fd, i;
+
+       if (!node)
+               return false;
+
+       node_path = node_path_get(node);
+
+       if (strlen(node_path) + strlen(dev_key_dir) + 1 + 4 >= PATH_MAX)
+               return false;
+
+       snprintf(key_file, PATH_MAX, "%s%s", node_path, dev_key_dir);
+       mkdir(key_file, 0755);
+
+       for (i = 0; i < count; i++) {
+               snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path,
+                                               dev_key_dir, unicast + i);
+               l_debug("Put Dev Key %s", key_file);
+
+               fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC);
+               if (fd >= 0) {
+                       if (write(fd, dev_key, 16) != 16)
+                               result = false;
+
+                       close(fd);
+               } else
+                       result = false;
+       }
+
+       return result;
+}
+
+bool keyring_get_net_key(struct mesh_node *node, uint16_t net_idx,
+                                               struct keyring_net_key *key)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = false;
+       int fd;
+
+       if (!node || !key)
+               return false;
+
+       node_path = node_path_get(node);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir,
+                                                               net_idx);
+
+       fd = open(key_file, O_RDONLY);
+       if (fd >= 0) {
+               if (read(fd, key, sizeof(*key)) == sizeof(*key))
+                       result = true;
+
+               close(fd);
+       }
+
+       return result;
+}
+
+bool keyring_get_app_key(struct mesh_node *node, uint16_t app_idx,
+                                               struct keyring_app_key *key)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = false;
+       int fd;
+
+       if (!node || !key)
+               return false;
+
+       node_path = node_path_get(node);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir,
+                                                               app_idx);
+
+       fd = open(key_file, O_RDONLY);
+       if (fd >= 0) {
+               if (read(fd, key, sizeof(*key)) == sizeof(*key))
+                       result = true;
+
+               close(fd);
+       }
+
+       return result;
+}
+
+bool keyring_get_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                                       uint8_t dev_key[16])
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       bool result = false;
+       int fd;
+
+       if (!node)
+               return false;
+
+       node_path = node_path_get(node);
+       snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path, dev_key_dir,
+                                                               unicast);
+
+       fd = open(key_file, O_RDONLY);
+       if (fd >= 0) {
+               if (read(fd, dev_key, 16) == 16)
+                       result = true;
+
+               close(fd);
+       }
+
+       return result;
+}
+
+bool keyring_del_net_key(struct mesh_node *node, uint16_t net_idx)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+
+       if (!node)
+               return false;
+
+       node_path = node_path_get(node);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir,
+                                                               net_idx);
+       l_debug("RM Net Key %s", key_file);
+       remove(key_file);
+
+       /* TODO: See if it is easiest to delete all bound App keys here */
+       /* TODO: see nftw() */
+
+       return true;
+}
+
+bool keyring_del_app_key(struct mesh_node *node, uint16_t app_idx)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+
+       if (!node)
+               return false;
+
+       node_path = node_path_get(node);
+       snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir,
+                                                               app_idx);
+       l_debug("RM App Key %s", key_file);
+       remove(key_file);
+
+       return true;
+}
+
+bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                                               uint8_t count)
+{
+       char *node_path;
+       char key_file[PATH_MAX];
+       int i;
+
+       if (!node)
+               return false;
+
+       node_path = node_path_get(node);
+       for (i = 0; i < count; i++) {
+               snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path,
+                                               dev_key_dir, unicast + i);
+               l_debug("RM Dev Key %s", key_file);
+               remove(key_file);
+       }
+
+       return true;
+}
diff --git a/mesh/keyring.h b/mesh/keyring.h
new file mode 100644 (file)
index 0000000..1671910
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2019  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.
+ *
+ */
+
+struct keyring_net_key {
+       uint16_t net_idx;
+       uint8_t phase;
+       uint8_t old_key[16];
+       uint8_t new_key[16];
+};
+
+struct keyring_app_key {
+       uint16_t app_idx;
+       uint16_t net_idx;
+       uint8_t old_key[16];
+       uint8_t new_key[16];
+};
+
+bool keyring_put_net_key(struct mesh_node *node, uint16_t net_idx,
+                                               struct keyring_net_key *key);
+bool keyring_get_net_key(struct mesh_node *node, uint16_t net_idx,
+                                               struct keyring_net_key *key);
+bool keyring_del_net_key(struct mesh_node *node, uint16_t net_idx);
+bool keyring_put_app_key(struct mesh_node *node, uint16_t app_idx,
+                               uint16_t net_idx, struct keyring_app_key *key);
+bool keyring_get_app_key(struct mesh_node *node, uint16_t app_idx,
+                                               struct keyring_app_key *key);
+bool keyring_del_app_key(struct mesh_node *node, uint16_t app_idx);
+bool keyring_get_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                                       uint8_t dev_key[16]);
+bool keyring_put_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                       uint8_t count, uint8_t dev_key[16]);
+bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast,
+                                                               uint8_t count);