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. --- Makefile.mesh | 1 + mesh/keyring.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mesh/keyring.h | 49 ++++++++++ 3 files changed, 348 insertions(+) create mode 100644 mesh/keyring.c create mode 100644 mesh/keyring.h diff --git a/Makefile.mesh b/Makefile.mesh index 76e424b92..bccd4d946 100644 --- a/Makefile.mesh +++ b/Makefile.mesh @@ -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 index 000000000..59aa1eaf4 --- /dev/null +++ b/mesh/keyring.c @@ -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 index 000000000..167191013 --- /dev/null +++ b/mesh/keyring.h @@ -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); -- 2.14.5