--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef BT_SERVICE_MESH_UTIL_H_
+#define BT_SERVICE_MESH_UTIL_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "bluetooth-mesh-api.h"
+#include <json-c/json.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MESH_FEATURE_RELAY 1
+#define MESH_FEATURE_PROXY 2
+#define MESH_FEATURE_FRIEND 4
+#define MESH_FEATURE_LPN 8
+
+#define MESH_DEFAULT_LOCATION 0x0000
+
+#define MESH_CDB_DEFAULT_DIR_PATH "/opt/usr/mesh"
+
+/* Status codes */
+#define MESH_STATUS_SUCCESS 0x00
+#define MESH_STATUS_INVALID_ADDRESS 0x01
+#define MESH_STATUS_INVALID_MODEL 0x02
+#define MESH_STATUS_INVALID_APPKEY 0x03
+#define MESH_STATUS_INVALID_NETKEY 0x04
+#define MESH_STATUS_INSUFF_RESOURCES 0x05
+#define MESH_STATUS_IDX_ALREADY_STORED 0x06
+#define MESH_STATUS_INVALID_PUB_PARAM 0x07
+#define MESH_STATUS_NOT_SUB_MOD 0x08
+#define MESH_STATUS_STORAGE_FAIL 0x09
+#define MESH_STATUS_FEATURE_NO_SUPPORT 0x0a
+#define MESH_STATUS_CANNOT_UPDATE 0x0b
+#define MESH_STATUS_CANNOT_REMOVE 0x0c
+#define MESH_STATUS_CANNOT_BIND 0x0d
+#define MESH_STATUS_UNABLE_CHANGE_STATE 0x0e
+#define MESH_STATUS_CANNOT_SET 0x0f
+#define MESH_STATUS_UNSPECIFIED_ERROR 0x10
+#define MESH_STATUS_INVALID_BINDING 0x11
+
+#define MESH_UNASSIGNED_ADDRESS 0x0000
+#define MESH_PROXIES_ADDRESS 0xfffc
+#define MESH_FRIENDS_ADDRESS 0xfffd
+#define MESH_RELAYS_ADDRESS 0xfffe
+#define MESH_ALL_NODES_ADDRESS 0xffff
+#define MESH_VIRTUAL_ADDRESS_LOW 0x8000
+#define MESH_VIRTUAL_ADDRESS_HIGH 0xbfff
+#define MESH_GROUP_ADDRESS_LOW 0xc000
+#define MESH_GROUP_ADDRESS_HIGH 0xfeff
+#define MESH_FIXED_GROUP_LOW 0xff00
+#define MESH_FIXED_GROUP_HIGH 0xffff
+
+#define MESH_DEFAULT_START_ADDRESS 0x00aa
+#define MESH_DEFAULT_MAX_ADDRESS (MESH_VIRTUAL_ADDRESS_LOW - 1)
+#define MESH_IS_VIRTUAL(x) (((x) >= MESH_VIRTUAL_ADDRESS_LOW) && \
+ ((x) <= MESH_VIRTUAL_ADDRESS_HIGH))
+#define MESH_IS_GROUP(x) ((((x) >= MESH_GROUP_ADDRESS_LOW) && \
+ ((x) < MESH_FIXED_GROUP_HIGH)) || \
+ ((x) == MESH_ALL_NODES_ADDRESS))
+
+#define MESH_IS_FIXED_GROUP_ADDRESS(x) ((x) >= MESH_PROXIES_ADDRESS)
+#define MESH_IS_ALL_NODES(x) ((x) == MESH_ALL_NODES_ADDRESS)
+
+#define MESH_DEFAULT_NET_INDEX 0x0000
+#define MESH_MAX_CRPL_SIZE 0x7fff
+
+#define MESH_PRIMARY_ELE_IDX 0x00
+
+#define MESH_PRIMARY_NET_IDX 0x0000
+#define MESH_MAX_KEY_IDX 0x0fff
+#define MESH_MAX_MODEL_COUNT 0xff
+#define MESH_MAX_ELE_COUNT 0xff
+
+#define MESH_KEY_REFRESH_PHASE_NONE 0x00
+#define MESH_KEY_REFRESH_PHASE_ONE 0x01
+#define MESH_KEY_REFRESH_PHASE_TWO 0x03
+#define MESH_KEY_REFRESH_PHASE_THREE 0x02
+
+#define MESH_NET_IDX_INVALID 0xffff
+#define MESH_NET_NID_INVALID 0xff
+
+#define MESH_KEY_IDX_INVALID MESH_NET_IDX_INVALID
+#define MESH_VENDOR_ID_MASK 0xffff0000
+
+#define MESH_DEFAULT_RESPONSE_TIMEOUT 3
+#define MESH_RESPONSE_NONE 0xFFFFFFFF
+
+#define MESH_OPCODE_UNRELIABLE 0x0100
+#define MESH_MINIMUM_COMPOSITION_LEN 16
+
+/* New List */
+#define MESH_OPCODE_APPKEY_ADD 0x00
+#define MESH_OPCODE_APPKEY_DELETE 0x8000
+#define MESH_OPCODE_APPKEY_GET 0x8001
+#define MESH_OPCODE_APPKEY_LIST 0x8002
+#define MESH_OPCODE_APPKEY_STATUS 0x8003
+#define MESH_OPCODE_APPKEY_UPDATE 0x01
+#define MESH_OPCODE_DEV_COMP_GET 0x8008
+#define MESH_OPCODE_DEV_COMP_STATUS 0x02
+#define MESH_OPCODE_CONFIG_BEACON_GET 0x8009
+#define MESH_OPCODE_CONFIG_BEACON_SET 0x800A
+#define MESH_OPCODE_CONFIG_BEACON_STATUS 0x800B
+#define MESH_OPCODE_CONFIG_DEFAULT_TTL_GET 0x800C
+#define MESH_OPCODE_CONFIG_DEFAULT_TTL_SET 0x800D
+#define MESH_OPCODE_CONFIG_DEFAULT_TTL_STATUS 0x800E
+#define MESH_OPCODE_CONFIG_FRIEND_GET 0x800F
+#define MESH_OPCODE_CONFIG_FRIEND_SET 0x8010
+#define MESH_OPCODE_CONFIG_FRIEND_STATUS 0x8011
+#define MESH_OPCODE_CONFIG_PROXY_GET 0x8012
+#define MESH_OPCODE_CONFIG_PROXY_SET 0x8013
+#define MESH_OPCODE_CONFIG_PROXY_STATUS 0x8014
+#define MESH_OPCODE_CONFIG_KEY_REFRESH_PHASE_GET 0x8015
+#define MESH_OPCODE_CONFIG_KEY_REFRESH_PHASE_SET 0x8016
+#define MESH_OPCODE_CONFIG_KEY_REFRESH_PHASE_STATUS 0x8017
+#define MESH_OPCODE_CONFIG_MODEL_PUB_GET 0x8018
+#define MESH_OPCODE_CONFIG_MODEL_PUB_SET 0x03
+#define MESH_OPCODE_CONFIG_MODEL_PUB_STATUS 0x8019
+#define MESH_OPCODE_CONFIG_MODEL_PUB_VIRT_SET 0x801A
+#define MESH_OPCODE_CONFIG_MODEL_SUB_ADD 0x801B
+#define MESH_OPCODE_CONFIG_MODEL_SUB_DELETE 0x801C
+#define MESH_OPCODE_CONFIG_MODEL_SUB_DELETE_ALL 0x801D
+#define MESH_OPCODE_CONFIG_MODEL_SUB_OVERWRITE 0x801E
+#define MESH_OPCODE_CONFIG_MODEL_SUB_STATUS 0x801F
+#define MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_ADD 0x8020
+#define MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_DELETE 0x8021
+#define MESH_OPCODE_CONFIG_MODEL_SUB_VIRT_OVERWRITE 0x8022
+#define MESH_OPCODE_CONFIG_NETWORK_TRANSMIT_GET 0x8023
+#define MESH_OPCODE_CONFIG_NETWORK_TRANSMIT_SET 0x8024
+#define MESH_OPCODE_CONFIG_NETWORK_TRANSMIT_STATUS 0x8025
+#define MESH_OPCODE_CONFIG_RELAY_GET 0x8026
+#define MESH_OPCODE_CONFIG_RELAY_SET 0x8027
+#define MESH_OPCODE_CONFIG_RELAY_STATUS 0x8028
+#define MESH_OPCODE_CONFIG_MODEL_SUB_GET 0x8029
+#define MESH_OPCODE_CONFIG_MODEL_SUB_LIST 0x802A
+#define MESH_OPCODE_CONFIG_VEND_MODEL_SUB_GET 0x802B
+#define MESH_OPCODE_CONFIG_VEND_MODEL_SUB_LIST 0x802C
+#define MESH_OPCODE_CONFIG_POLL_TIMEOUT_LIST 0x802D
+#define MESH_OPCODE_CONFIG_POLL_TIMEOUT_STATUS 0x802E
+/* Health opcodes in health-mod.h */
+#define MESH_OPCODE_CONFIG_HEARTBEAT_PUB_GET 0x8038
+#define MESH_OPCODE_CONFIG_HEARTBEAT_PUB_SET 0x8039
+#define MESH_OPCODE_CONFIG_HEARTBEAT_PUB_STATUS 0x06
+#define MESH_OPCODE_CONFIG_HEARTBEAT_SUB_GET 0x803A
+#define MESH_OPCODE_CONFIG_HEARTBEAT_SUB_SET 0x803B
+#define MESH_OPCODE_CONFIG_HEARTBEAT_SUB_STATUS 0x803C
+#define MESH_OPCODE_MODEL_APP_BIND 0x803D
+#define MESH_OPCODE_MODEL_APP_STATUS 0x803E
+#define MESH_OPCODE_MODEL_APP_UNBIND 0x803F
+#define MESH_OPCODE_NETKEY_ADD 0x8040
+#define MESH_OPCODE_NETKEY_DELETE 0x8041
+#define MESH_OPCODE_NETKEY_GET 0x8042
+#define MESH_OPCODE_NETKEY_LIST 0x8043
+#define MESH_OPCODE_NETKEY_STATUS 0x8044
+#define MESH_OPCODE_NETKEY_UPDATE 0x8045
+#define MESH_OPCODE_NODE_IDENTITY_GET 0x8046
+#define MESH_OPCODE_NODE_IDENTITY_SET 0x8047
+#define MESH_OPCODE_NODE_IDENTITY_STATUS 0x8048
+#define MESH_OPCODE_NODE_RESET 0x8049
+#define MESH_OPCODE_NODE_RESET_STATUS 0x804A
+#define MESH_OPCODE_MODEL_APP_GET 0x804B
+#define MESH_OPCODE_MODEL_APP_LIST 0x804C
+#define MESH_OPCODE_VENDOR_MODEL_APP_GET 0x804D
+#define MESH_OPCODE_VENDOR_MODEL_APP_LIST 0x804E
+
+
+uint32_t _bt_mesh_util_get_timestamp_secs(void);
+
+bool _bt_mesh_util_convert_string_to_hex(const char *str,
+ uint16_t in_len, uint8_t *out,
+ uint16_t out_len);
+
+size_t _bt_mesh_util_convert_hex_to_string(uint8_t *in,
+ size_t in_len, char *out, size_t out_len);
+
+void _bt_mesh_util_print_packet(const char *label,
+ const void *data, uint16_t size);
+
+bool _bt_mesh_util_create_directory(const char *dir_name);
+
+bool _bt_mesh_util_is_directory_exists(const char *dir_path);
+
+uint16_t _bt_mesh_util_opcode_set(uint32_t opcode,
+ uint8_t *buf);
+
+bool _bt_mesh_util_opcode_get(const uint8_t *buf,
+ uint16_t sz, uint32_t *opcode, int *n);
+
+bool _bt_mesh_util_crypto_s1(const void *info, size_t len,
+ uint8_t salt[16]);
+
+bool _bt_mesh_util_crypto_create_virtual_address(
+ const uint8_t virtual_label[16],
+ uint16_t *addr);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* BT_SERVICE_MESH_UTIL_H_ */
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing prov_err_strs and
+ * limitations under the License.
+ *
+ */
+#include <dirent.h>
+#include <ftw.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <dlog.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "bt-service-common.h"
+#include "bt-service-util.h"
+
+#include "bt-service-mesh-util.h"
+#include <ell/ell.h>
+
+/* Multiply used Zero array */
+static const uint8_t zero[16] = { 0, };
+
+static bool __mesh_util_crypto_aes_cmac_one(
+ const uint8_t key[16], const void *msg,
+ size_t msg_len, uint8_t res[16])
+{
+ void *checksum;
+ bool result;
+
+ checksum = l_checksum_new_cmac_aes(key, 16);
+ if (!checksum)
+ return false;
+
+ result = l_checksum_update(checksum, msg, msg_len);
+
+ if (result) {
+ ssize_t len = l_checksum_get_digest(checksum, res, 16);
+ result = !!(len == 16);
+ }
+
+ l_checksum_free(checksum);
+
+ return result;
+}
+
+bool _bt_mesh_util_crypto_s1(const void *info,
+ size_t len, uint8_t salt[16])
+{
+ return __mesh_util_crypto_aes_cmac_one(zero,
+ info, len, salt);
+}
+
+bool _bt_mesh_util_crypto_create_virtual_address(
+ const uint8_t virtual_label[16], uint16_t *addr)
+{
+ uint8_t tmp[16];
+
+ if (!_bt_mesh_util_crypto_s1("vtad", 4, tmp))
+ return false;
+
+ if (!addr || !__mesh_util_crypto_aes_cmac_one(tmp,
+ virtual_label, 16, tmp))
+ return false;
+
+ *addr = (l_get_be16(tmp + 14) & 0x3fff) | 0x8000;
+ return true;
+}
+
+void _bt_mesh_util_print_byte_array(const char *prefix,
+ const void *ptr, int len)
+{
+ const uint8_t *data = ptr;
+ char *line, *bytes;
+ int i;
+
+ line = g_malloc(strlen(prefix) + (16 * 3) + 2);
+ sprintf(line, "%s ", prefix);
+ bytes = line + strlen(prefix) + 1;
+
+ for (i = 0; i < len; ++i) {
+ sprintf(bytes, "%2.2x ", data[i]);
+ if ((i + 1) % 16) {
+ bytes += 3;
+ } else {
+ BT_INFO("\r%s\n", line);
+ bytes = line + strlen(prefix) + 1;
+ }
+ }
+
+ if (i % 16)
+ BT_INFO("\r%s\n", line);
+
+ g_free(line);
+}
+
+uint16_t _bt_mesh_util_opcode_set(uint32_t opcode,
+ uint8_t *buf)
+{
+ if (opcode <= 0x7e) {
+ buf[0] = opcode;
+ return 1;
+ } else if (opcode >= 0x8000 && opcode <= 0xbfff) {
+ l_put_be16(opcode, buf);
+ return 2;
+ } else if (opcode >= 0xc00000 && opcode <= 0xffffff) {
+ buf[0] = (opcode >> 16) & 0xff;
+ l_put_be16(opcode, buf + 1);
+ return 3;
+ } else
+ return 0;
+}
+
+bool _bt_mesh_util_opcode_get(const uint8_t *buf,
+ uint16_t sz, uint32_t *opcode, int *n)
+{
+ BT_INFO("Mesh: Opcode Get DatLen [%d] Buf0 [0x%x]",
+ sz, buf[0]);
+ if (!n || !opcode || sz < 1) return false;
+
+ switch (buf[0] & 0xc0) {
+ case 0x00:
+ case 0x40:
+ /* RFU */
+ if (buf[0] == 0x7f)
+ return false;
+
+ *n = 1;
+ *opcode = buf[0];
+ break;
+
+ case 0x80:
+ if (sz < 2)
+ return false;
+
+ *n = 2;
+ *opcode = l_get_be16(buf);
+ break;
+
+ case 0xc0:
+ if (sz < 3)
+ return false;
+
+ *n = 3;
+ *opcode = l_get_be16(buf + 1);
+ *opcode |= buf[0] << 16;
+ break;
+
+ default:
+ BT_ERR("Mesh: Bad Packet:\n");
+ _bt_mesh_util_print_byte_array("\t", (void *) buf, sz);
+ return false;
+ }
+
+ return true;
+}
+
+
+uint32_t _bt_mesh_util_get_timestamp_secs(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec;
+}
+
+bool _bt_mesh_util_convert_string_to_hex(const char *str,
+ uint16_t in_len, uint8_t *out,
+ uint16_t out_len)
+{
+ uint16_t i;
+
+ if (in_len < out_len * 2)
+ return false;
+
+ for (i = 0; i < out_len; i++) {
+ if (sscanf(&str[i * 2], "%02hhx", &out[i]) != 1)
+ return false;
+ }
+
+ return true;
+}
+
+size_t _bt_mesh_util_convert_hex_to_string(uint8_t *in,
+ size_t in_len, char *out, size_t out_len)
+{
+ static const char hexdigits[] = "0123456789abcdef";
+ size_t i;
+
+ if (in_len * 2 > (out_len - 1))
+ return 0;
+
+ for (i = 0; i < in_len; i++) {
+ out[i * 2] = hexdigits[in[i] >> 4];
+ out[i * 2 + 1] = hexdigits[in[i] & 0xf];
+ }
+
+ out[in_len * 2] = '\0';
+ return i;
+}
+
+void _bt_mesh_util_print_packet(const char *label,
+ const void *data, uint16_t size)
+{
+ struct timeval pkt_time;
+
+ gettimeofday(&pkt_time, NULL);
+
+ if (size > 0) {
+ char *str;
+
+ str = l_util_hexstring(data, size);
+ BT_DBG("%05d.%03d %s: %s",
+ (uint32_t) pkt_time.tv_sec % 100000,
+ (uint32_t) pkt_time.tv_usec/1000, label, str);
+ l_free(str);
+ } else
+ BT_DBG("%05d.%03d %s: empty",
+ (uint32_t) pkt_time.tv_sec % 100000,
+ (uint32_t) pkt_time.tv_usec/1000, label);
+}
+
+bool _bt_mesh_util_create_directory(const char *mesh_dir)
+{
+ struct stat st;
+ BT_ERR("Mesh: Create [%s]", mesh_dir);
+
+ if (stat(mesh_dir, &st) == 0) {
+ if (!S_ISDIR(st.st_mode)) {
+ BT_ERR("Mesh: [%s] not a directory", mesh_dir);
+ return false;
+ }
+ } else if (errno == ENOENT) {
+ BT_ERR("Mesh: Dir not available: [%s]", mesh_dir);
+ if (mkdir(mesh_dir, 0755) != 0) {
+ BT_ERR("Mesh: Dir creation failed: [%s] error [%d]",
+ mesh_dir, errno);
+ return false;
+ }
+ } else {
+ BT_ERR("Mesh: Cannot open config directory");
+ return false;
+ }
+
+ return true;
+}
+
+bool _bt_mesh_util_is_directory_exists(const char *dir_path)
+{
+ struct stat st;
+
+ if (stat(dir_path, &st) == 0) {
+ if (!S_ISDIR(st.st_mode)) {
+ BT_ERR("Mesh: [%s] not a directory", dir_path);
+ return false;
+ }
+ } else if (errno == ENOENT) {
+ return false;
+ }
+
+ return true;
+}