Fix the coverity issues
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-util.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
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
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <ftw.h>
24 #include <unistd.h>
25 #include <stdio.h>
26
27 #include <glib.h>
28 #include <dlog.h>
29 #include <limits.h>
30 #include <time.h>
31 #include <sys/time.h>
32
33 #include "bt-service-common.h"
34 #include "bt-service-util.h"
35
36 #include "bt-service-mesh-util.h"
37 #include <ell/ell.h>
38
39 /* Multiply used Zero array */
40 static const uint8_t zero[16] = { 0, };
41
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])
45 {
46         void *checksum;
47         bool result;
48
49         checksum = l_checksum_new_cmac_aes(key, 16);
50         if (!checksum)
51                 return false;
52
53         result = l_checksum_update(checksum, msg, msg_len);
54
55         if (result) {
56                 ssize_t len = l_checksum_get_digest(checksum, res, 16);
57                 result = !!(len == 16);
58         }
59
60         l_checksum_free(checksum);
61
62         return result;
63 }
64
65 bool _bt_mesh_util_crypto_s1(const void *info,
66                 size_t len, uint8_t salt[16])
67 {
68         return __mesh_util_crypto_aes_cmac_one(zero,
69                         info, len, salt);
70 }
71
72 bool _bt_mesh_util_crypto_create_virtual_address(
73         const uint8_t virtual_label[16], uint16_t *addr)
74 {
75         uint8_t tmp[16];
76
77         if (!_bt_mesh_util_crypto_s1("vtad", 4, tmp))
78                 return false;
79
80         if (!addr || !__mesh_util_crypto_aes_cmac_one(tmp,
81                         virtual_label, 16, tmp))
82                 return false;
83
84         *addr = (l_get_be16(tmp + 14) & 0x3fff) | 0x8000;
85         return true;
86 }
87
88 void _bt_mesh_util_print_byte_array(const char *prefix,
89                 const void *ptr, int len)
90 {
91         const uint8_t *data = ptr;
92         char *line, *bytes;
93         int i;
94
95         line = g_malloc(strlen(prefix) + (16 * 3) + 2);
96         snprintf(line, strlen(prefix), "%s ", prefix);
97         bytes = line + strlen(prefix) + 1;
98
99         for (i = 0; i < len; ++i) {
100                 snprintf(bytes, 4, "%2.2x ", data[i]);
101                 if ((i + 1) % 16) {
102                         bytes += 3;
103                 } else {
104                         BT_INFO("\r%s\n", line);
105                         bytes = line + strlen(prefix) + 1;
106                 }
107         }
108
109         if (i % 16)
110                 BT_INFO("\r%s\n", line);
111
112         g_free(line);
113 }
114
115 uint16_t _bt_mesh_util_opcode_set(uint32_t opcode,
116                 uint8_t *buf)
117 {
118         if (opcode <= 0x7e) {
119                 buf[0] = opcode;
120                 return 1;
121         } else if (opcode >= 0x8000 && opcode <= 0xbfff) {
122                 l_put_be16(opcode, buf);
123                 return 2;
124         } else if (opcode >= 0xc00000 && opcode <= 0xffffff) {
125                 buf[0] = (opcode >> 16) & 0xff;
126                 l_put_be16(opcode, buf + 1);
127                 return 3;
128         } else {
129                 return 0;
130         }
131 }
132
133 bool _bt_mesh_util_opcode_get(const uint8_t *buf,
134                 uint16_t sz, uint32_t *opcode, int *n)
135 {
136         BT_INFO("Mesh: Opcode Get DatLen [%d] Buf0 [0x%x]",
137                         sz, buf[0]);
138         if (!n || !opcode || sz < 1) return false;
139
140         switch (buf[0] & 0xc0) {
141         case 0x00:
142         case 0x40:
143                 /* RFU */
144                 if (buf[0] == 0x7f)
145                         return false;
146
147                 *n = 1;
148                 *opcode = buf[0];
149                 break;
150
151         case 0x80:
152                 if (sz < 2)
153                         return false;
154
155                 *n = 2;
156                 *opcode = l_get_be16(buf);
157                 break;
158
159         case 0xc0:
160                 if (sz < 3)
161                         return false;
162
163                 *n = 3;
164                 *opcode = l_get_be16(buf + 1);
165                 *opcode |= buf[0] << 16;
166                 break;
167
168         default:
169                 BT_ERR("Mesh: Bad Packet:\n");
170                 _bt_mesh_util_print_byte_array("\t", (void *) buf, sz);
171                 return false;
172         }
173
174         return true;
175 }
176
177
178 uint32_t _bt_mesh_util_get_timestamp_secs(void)
179 {
180         struct timespec ts;
181
182         clock_gettime(CLOCK_MONOTONIC, &ts);
183         return ts.tv_sec;
184 }
185
186 bool _bt_mesh_util_convert_string_to_hex(const char *str,
187         uint16_t in_len, uint8_t *out,
188                 uint16_t out_len)
189 {
190         uint16_t i;
191
192         if (in_len < out_len * 2)
193                 return false;
194
195         for (i = 0; i < out_len; i++) {
196                 if (sscanf(&str[i * 2], "%02hhx", &out[i]) != 1)
197                         return false;
198         }
199
200         return true;
201 }
202
203 size_t _bt_mesh_util_convert_hex_to_string(uint8_t *in,
204                 size_t in_len, char *out, size_t out_len)
205 {
206         static const char hexdigits[] = "0123456789abcdef";
207         size_t i;
208
209         if (in_len * 2 > (out_len - 1))
210                 return 0;
211
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];
215         }
216
217         out[in_len * 2] = '\0';
218         return i;
219 }
220
221 void _bt_mesh_util_print_packet(const char *label,
222                 const void *data, uint16_t size)
223 {
224         struct timeval pkt_time;
225
226         gettimeofday(&pkt_time, NULL);
227
228         if (size > 0) {
229                 char *str;
230
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);
235                 l_free(str);
236         } else
237                 BT_DBG("%05d.%03d %s: empty",
238                                 (uint32_t) pkt_time.tv_sec % 100000,
239                                 (uint32_t) pkt_time.tv_usec/1000, label);
240 }
241
242 bool _bt_mesh_util_create_directory(const char *mesh_dir)
243 {
244         struct stat st;
245         BT_ERR("Mesh: Create [%s]", mesh_dir);
246
247         if (stat(mesh_dir, &st) == 0) {
248                 if (!S_ISDIR(st.st_mode)) {
249                         BT_ERR("Mesh: [%s] not a directory", mesh_dir);
250                         return false;
251                 }
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]",
256                                 mesh_dir, errno);
257                         return false;
258                 }
259         } else {
260                 BT_ERR("Mesh: Cannot open config directory");
261                 return false;
262         }
263
264         return true;
265 }
266
267 bool _bt_mesh_util_delete_file(const char *filename)
268 {
269         struct stat st;
270         int fd;
271
272         fd = open(filename, O_RDONLY);
273         if (fd < 0) {
274                 BT_ERR("Mesh: Failed to open [%s]", filename);
275                 return false;
276         }
277
278         if (fstat(fd, &st) < 0) {
279                 BT_ERR("Mesh: Failed to stat [%s]", filename);
280                 close(fd);
281                 return false;
282         }
283
284         if (S_ISREG(st.st_mode)) {
285                 BT_INFO("Mesh: Failed stat: success [%s]", filename);
286                 close(fd);
287                 remove(filename);
288                 return true;
289         } else {
290                 BT_ERR("Mesh: [%s] Is not a regular file", filename);
291         }
292
293         BT_INFO("Mesh: File [%s] deleted", filename);
294         close(fd);
295         return false;
296 }
297
298 bool _bt_mesh_util_is_directory_exists(const char *dir_path)
299 {
300         struct stat st;
301
302         if (stat(dir_path, &st) == 0) {
303                 if (!S_ISDIR(st.st_mode)) {
304                         BT_ERR("Mesh: [%s] not a directory", dir_path);
305                         return false;
306                 }
307         } else if (errno == ENOENT) {
308                 return false;
309         }
310
311         return true;
312 }