4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * @author: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing prov_err_strs and
18 * limitations under the License.
33 #include "bt-service-common.h"
34 #include "bt-service-util.h"
36 #include "bt-service-mesh-util.h"
39 /* Multiply used Zero array */
40 static const uint8_t zero[16] = { 0, };
42 static bool __mesh_util_crypto_aes_cmac_one(
43 const uint8_t key[16], const void *msg,
44 size_t msg_len, uint8_t res[16])
49 checksum = l_checksum_new_cmac_aes(key, 16);
53 result = l_checksum_update(checksum, msg, msg_len);
56 ssize_t len = l_checksum_get_digest(checksum, res, 16);
57 result = !!(len == 16);
60 l_checksum_free(checksum);
65 bool _bt_mesh_util_crypto_s1(const void *info,
66 size_t len, uint8_t salt[16])
68 return __mesh_util_crypto_aes_cmac_one(zero,
72 bool _bt_mesh_util_crypto_create_virtual_address(
73 const uint8_t virtual_label[16], uint16_t *addr)
77 if (!_bt_mesh_util_crypto_s1("vtad", 4, tmp))
80 if (!addr || !__mesh_util_crypto_aes_cmac_one(tmp,
81 virtual_label, 16, tmp))
84 *addr = (l_get_be16(tmp + 14) & 0x3fff) | 0x8000;
88 void _bt_mesh_util_print_byte_array(const char *prefix,
89 const void *ptr, int len)
91 const uint8_t *data = ptr;
95 line = g_malloc(strlen(prefix) + (16 * 3) + 2);
96 snprintf(line, strlen(prefix), "%s ", prefix);
97 bytes = line + strlen(prefix) + 1;
99 for (i = 0; i < len; ++i) {
100 snprintf(bytes, 4, "%2.2x ", data[i]);
104 BT_INFO("\r%s\n", line);
105 bytes = line + strlen(prefix) + 1;
110 BT_INFO("\r%s\n", line);
115 uint16_t _bt_mesh_util_opcode_set(uint32_t opcode,
118 if (opcode <= 0x7e) {
121 } else if (opcode >= 0x8000 && opcode <= 0xbfff) {
122 l_put_be16(opcode, buf);
124 } else if (opcode >= 0xc00000 && opcode <= 0xffffff) {
125 buf[0] = (opcode >> 16) & 0xff;
126 l_put_be16(opcode, buf + 1);
133 bool _bt_mesh_util_opcode_get(const uint8_t *buf,
134 uint16_t sz, uint32_t *opcode, int *n)
136 BT_INFO("Mesh: Opcode Get DatLen [%d] Buf0 [0x%x]",
138 if (!n || !opcode || sz < 1) return false;
140 switch (buf[0] & 0xc0) {
156 *opcode = l_get_be16(buf);
164 *opcode = l_get_be16(buf + 1);
165 *opcode |= buf[0] << 16;
169 BT_ERR("Mesh: Bad Packet:\n");
170 _bt_mesh_util_print_byte_array("\t", (void *) buf, sz);
178 uint32_t _bt_mesh_util_get_timestamp_secs(void)
182 clock_gettime(CLOCK_MONOTONIC, &ts);
186 bool _bt_mesh_util_convert_string_to_hex(const char *str,
187 uint16_t in_len, uint8_t *out,
192 if (in_len < out_len * 2)
195 for (i = 0; i < out_len; i++) {
196 if (sscanf(&str[i * 2], "%02hhx", &out[i]) != 1)
203 size_t _bt_mesh_util_convert_hex_to_string(uint8_t *in,
204 size_t in_len, char *out, size_t out_len)
206 static const char hexdigits[] = "0123456789abcdef";
209 if (in_len * 2 > (out_len - 1))
212 for (i = 0; i < in_len; i++) {
213 out[i * 2] = hexdigits[in[i] >> 4];
214 out[i * 2 + 1] = hexdigits[in[i] & 0xf];
217 out[in_len * 2] = '\0';
221 void _bt_mesh_util_print_packet(const char *label,
222 const void *data, uint16_t size)
224 struct timeval pkt_time;
226 gettimeofday(&pkt_time, NULL);
231 str = l_util_hexstring(data, size);
232 BT_DBG("%05d.%03d %s: %s",
233 (uint32_t) pkt_time.tv_sec % 100000,
234 (uint32_t) pkt_time.tv_usec/1000, label, str);
237 BT_DBG("%05d.%03d %s: empty",
238 (uint32_t) pkt_time.tv_sec % 100000,
239 (uint32_t) pkt_time.tv_usec/1000, label);
242 bool _bt_mesh_util_create_directory(const char *mesh_dir)
245 BT_ERR("Mesh: Create [%s]", mesh_dir);
247 if (stat(mesh_dir, &st) == 0) {
248 if (!S_ISDIR(st.st_mode)) {
249 BT_ERR("Mesh: [%s] not a directory", mesh_dir);
252 } else if (errno == ENOENT) {
253 BT_ERR("Mesh: Dir not available: [%s]", mesh_dir);
254 if (mkdir(mesh_dir, 0755) != 0) {
255 BT_ERR("Mesh: Dir creation failed: [%s] error [%d]",
260 BT_ERR("Mesh: Cannot open config directory");
267 bool _bt_mesh_util_delete_file(const char *filename)
272 fd = open(filename, O_RDONLY);
274 BT_ERR("Mesh: Failed to open [%s]", filename);
278 if (fstat(fd, &st) < 0) {
279 BT_ERR("Mesh: Failed to stat [%s]", filename);
283 if (S_ISREG(st.st_mode)) {
284 BT_INFO("Mesh: Failed stat: success [%s]", filename);
289 BT_ERR("Mesh: [%s] Is not a regular file", filename);
292 BT_INFO("Mesh: File [%s] deleted", filename);
297 bool _bt_mesh_util_is_directory_exists(const char *dir_path)
301 if (stat(dir_path, &st) == 0) {
302 if (!S_ISDIR(st.st_mode)) {
303 BT_ERR("Mesh: [%s] not a directory", dir_path);
306 } else if (errno == ENOENT) {